KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > SimpleBookmark


1 /*
2  * Copyright 2003 by Paulo Soares.
3  *
4  * The contents of this file are subject to the Mozilla Public License Version 1.1
5  * (the "License"); you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS" basis,
9  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10  * for the specific language governing rights and limitations under the License.
11  *
12  * The Original Code is 'iText, a free JAVA-PDF library'.
13  *
14  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
15  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
16  * All Rights Reserved.
17  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
18  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
19  *
20  * Contributor(s): all the names of the contributors are added in the source code
21  * where applicable.
22  *
23  * Alternatively, the contents of this file may be used under the terms of the
24  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
25  * provisions of LGPL are applicable instead of those above. If you wish to
26  * allow use of your version of this file only under the terms of the LGPL
27  * License and not to allow others to use your version of this file under
28  * the MPL, indicate your decision by deleting the provisions above and
29  * replace them with the notice and other provisions required by the LGPL.
30  * If you do not delete the provisions above, a recipient may use your version
31  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
32  *
33  * This library is free software; you can redistribute it and/or modify it
34  * under the terms of the MPL as stated above or under the terms of the GNU
35  * Library General Public License as published by the Free Software Foundation;
36  * either version 2 of the License, or any later version.
37  *
38  * This library is distributed in the hope that it will be useful, but WITHOUT
39  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
40  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
41  * details.
42  *
43  * If you didn't download this code from the following link, you should check if
44  * you aren't using an obsolete version:
45  * http://www.lowagie.com/iText/
46  */

47
48 package com.lowagie.text.pdf;
49
50 import java.io.BufferedWriter JavaDoc;
51 import java.io.IOException JavaDoc;
52 import java.io.InputStream JavaDoc;
53 import java.io.OutputStream JavaDoc;
54 import java.io.OutputStreamWriter JavaDoc;
55 import java.io.Reader JavaDoc;
56 import java.io.Writer JavaDoc;
57 import java.util.ArrayList JavaDoc;
58 import java.util.HashMap JavaDoc;
59 import java.util.Iterator JavaDoc;
60 import java.util.List JavaDoc;
61 import java.util.Map JavaDoc;
62 import java.util.Stack JavaDoc;
63 import java.util.StringTokenizer JavaDoc;
64
65 import com.lowagie.text.xml.simpleparser.IanaEncodings;
66 import com.lowagie.text.xml.simpleparser.SimpleXMLDocHandler;
67 import com.lowagie.text.xml.simpleparser.SimpleXMLParser;
68 /**
69  * Bookmark processing in a simple way. It has some limitations, mainly the only
70  * action types supported are GoTo, GoToR, URI and Launch.
71  * <p>
72  * The list structure is composed by a number of HashMap, keyed by strings, one HashMap
73  * for each bookmark.
74  * The element values are all strings with the exception of the key "Kids" that has
75  * another list for the child bookmarks.
76  * <p>
77  * All the bookmarks have a "Title" with the
78  * bookmark title and optionally a "Style" that can be "bold", "italic" or a
79  * combination of both. They can also have a "Color" key with a value of three
80  * floats separated by spaces. The key "Open" can have the values "true" or "false" and
81  * signals the open status of the children. It's "true" by default.
82  * <p>
83  * The actions and the parameters can be:
84  * <ul>
85  * <li>"Action" = "GoTo" - "Page" | "Named"
86  * <ul>
87  * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
88  * <li>"Named" = "named_destination"
89  * </ul>
90  * <li>"Action" = "GoToR" - "Page" | "Named" | "NamedN", "File", ["NewWindow"]
91  * <ul>
92  * <li>"Page" = "3 XYZ 70 400 null" - page number followed by a destination (/XYZ is also accepted)
93  * <li>"Named" = "named_destination_as_a_string"
94  * <li>"NamedN" = "named_destination_as_a_name"
95  * <li>"File" - "the_file_to_open"
96  * <li>"NewWindow" - "true" or "false"
97  * </ul>
98  * <li>"Action" = "URI" - "URI"
99  * <ul>
100  * <li>"URI" = "http://sf.net" - URI to jump to
101  * </ul>
102  * <li>"Action" = "Launch" - "File"
103  * <ul>
104  * <li>"File" - "the_file_to_open_or_execute"
105  * </ul>
106  * @author Paulo Soares (psoares@consiste.pt)
107  */

108 public class SimpleBookmark implements SimpleXMLDocHandler {
109     
110     private ArrayList JavaDoc topList;
111     private Stack JavaDoc attr = new Stack JavaDoc();
112     
113     /** Creates a new instance of SimpleBookmark */
114     private SimpleBookmark() {
115     }
116     
117     private static List JavaDoc bookmarkDepth(PdfReader reader, PdfDictionary outline, IntHashtable pages) {
118         ArrayList JavaDoc list = new ArrayList JavaDoc();
119         while (outline != null) {
120             HashMap JavaDoc map = new HashMap JavaDoc();
121             PdfString title = (PdfString)PdfReader.getPdfObjectRelease(outline.get(PdfName.TITLE));
122             map.put("Title", title.toUnicodeString());
123             PdfArray color = (PdfArray)PdfReader.getPdfObjectRelease(outline.get(PdfName.C));
124             if (color != null && color.getArrayList().size() == 3) {
125                 ByteBuffer out = new ByteBuffer();
126                 ArrayList JavaDoc arr = color.getArrayList();
127                 out.append(((PdfNumber)arr.get(0)).floatValue()).append(' ');
128                 out.append(((PdfNumber)arr.get(1)).floatValue()).append(' ');
129                 out.append(((PdfNumber)arr.get(2)).floatValue());
130                 map.put("Color", PdfEncodings.convertToString(out.toByteArray(), null));
131             }
132             PdfNumber style = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.F));
133             if (style != null) {
134                 int f = style.intValue();
135                 String JavaDoc s = "";
136                 if ((f & 1) != 0)
137                     s += "italic ";
138                 if ((f & 2) != 0)
139                     s += "bold ";
140                 s = s.trim();
141                 if (s.length() != 0)
142                     map.put("Style", s);
143             }
144             PdfNumber count = (PdfNumber)PdfReader.getPdfObjectRelease(outline.get(PdfName.COUNT));
145             if (count != null && count.intValue() < 0)
146                 map.put("Open", "false");
147             try {
148                 PdfObject dest = PdfReader.getPdfObjectRelease(outline.get(PdfName.DEST));
149                 if (dest != null) {
150                     mapGotoBookmark(map, dest, pages); //changed by ujihara 2004-06-13
151
}
152                 else {
153                     PdfDictionary action = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.A));
154                     if (action != null) {
155                         if (PdfName.GOTO.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
156                             dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
157                             if (dest != null) {
158                                 mapGotoBookmark(map, dest, pages);
159                             }
160                         }
161                         else if (PdfName.URI.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
162                             map.put("Action", "URI");
163                             map.put("URI", ((PdfString)PdfReader.getPdfObjectRelease(action.get(PdfName.URI))).toUnicodeString());
164                         }
165                         else if (PdfName.GOTOR.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
166                             dest = PdfReader.getPdfObjectRelease(action.get(PdfName.D));
167                             if (dest != null) {
168                                 if (dest.isString())
169                                     map.put("Named", dest.toString());
170                                 else if (dest.isName())
171                                     map.put("NamedN", PdfName.decodeName(dest.toString()));
172                                 else if (dest.isArray()) {
173                                     ArrayList JavaDoc arr = ((PdfArray)dest).getArrayList();
174                                     StringBuffer JavaDoc s = new StringBuffer JavaDoc();
175                                     s.append(arr.get(0).toString());
176                                     s.append(' ').append(arr.get(1).toString());
177                                     for (int k = 2; k < arr.size(); ++k)
178                                         s.append(' ').append(arr.get(k).toString());
179                                     map.put("Page", s.toString());
180                                 }
181                             }
182                             map.put("Action", "GoToR");
183                             PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
184                             if (file != null) {
185                                 if (file.isString())
186                                     map.put("File", ((PdfString)file).toUnicodeString());
187                                 else if (file.isDictionary()) {
188                                     file = PdfReader.getPdfObject(((PdfDictionary)file).get(PdfName.F));
189                                     if (file.isString())
190                                         map.put("File", ((PdfString)file).toUnicodeString());
191                                 }
192                             }
193                             PdfObject newWindow = PdfReader.getPdfObjectRelease(action.get(PdfName.NEWWINDOW));
194                             if (newWindow != null)
195                                 map.put("NewWindow", newWindow.toString());
196                         }
197                         else if (PdfName.LAUNCH.equals(PdfReader.getPdfObjectRelease(action.get(PdfName.S)))) {
198                             map.put("Action", "Launch");
199                             PdfObject file = PdfReader.getPdfObjectRelease(action.get(PdfName.F));
200                             if (file == null)
201                                 file = PdfReader.getPdfObjectRelease(action.get(PdfName.WIN));
202                             if (file != null) {
203                                 if (file.isString())
204                                     map.put("File", ((PdfString)file).toUnicodeString());
205                                 else if (file.isDictionary()) {
206                                     file = PdfReader.getPdfObjectRelease(((PdfDictionary)file).get(PdfName.F));
207                                     if (file.isString())
208                                         map.put("File", ((PdfString)file).toUnicodeString());
209                                 }
210                             }
211                         }
212                     }
213                 }
214             }
215             catch (Exception JavaDoc e) {
216                 //empty on purpose
217
}
218             PdfDictionary first = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.FIRST));
219             if (first != null) {
220                 map.put("Kids", bookmarkDepth(reader, first, pages));
221             }
222             list.add(map);
223             outline = (PdfDictionary)PdfReader.getPdfObjectRelease(outline.get(PdfName.NEXT));
224         }
225         return list;
226     }
227     
228     private static void mapGotoBookmark(HashMap JavaDoc map, PdfObject dest, IntHashtable pages)
229     {
230         if (dest.isString())
231             map.put("Named", dest.toString());
232         else if (dest.isName())
233             map.put("Named", PdfName.decodeName(dest.toString()));
234         else if (dest.isArray())
235             map.put("Page", makeBookmarkParam((PdfArray)dest, pages)); //changed by ujihara 2004-06-13
236
map.put("Action", "GoTo");
237     }
238
239     private static String JavaDoc makeBookmarkParam(PdfArray dest, IntHashtable pages)
240     {
241         ArrayList JavaDoc arr = dest.getArrayList();
242         StringBuffer JavaDoc s = new StringBuffer JavaDoc();
243         s.append(pages.get(getNumber((PdfIndirectReference)arr.get(0)))); //changed by ujihara 2004-06-13
244
s.append(' ').append(arr.get(1).toString().substring(1));
245         for (int k = 2; k < arr.size(); ++k)
246             s.append(' ').append(arr.get(k).toString());
247         return s.toString();
248     }
249     
250     /**
251      * Gets number of indirect. If type of directed indirect is PAGES, it refers PAGE object through KIDS.
252      * (Contributed by Kazuya Ujihara)
253      * @param indirect
254      * 2004-06-13
255      */

256     private static int getNumber(PdfIndirectReference indirect)
257     {
258         PdfDictionary pdfObj = (PdfDictionary)PdfReader.getPdfObjectRelease(indirect);
259         if (pdfObj.contains(PdfName.TYPE) && pdfObj.get(PdfName.TYPE).equals(PdfName.PAGES) && pdfObj.contains(PdfName.KIDS))
260         {
261             PdfArray kids = (PdfArray)pdfObj.get(PdfName.KIDS);
262             indirect = (PdfIndirectReference)kids.arrayList.get(0);
263         }
264         return indirect.getNumber();
265     }
266     
267     /**
268      * Gets a <CODE>List</CODE> with the bookmarks. It returns <CODE>null</CODE> if
269      * the document doesn't have any bookmarks.
270      * @param reader the document
271      * @return a <CODE>List</CODE> with the bookmarks or <CODE>null</CODE> if the
272      * document doesn't have any
273      */

274     public static List JavaDoc getBookmark(PdfReader reader) {
275         PdfDictionary catalog = reader.getCatalog();
276         PdfObject obj = PdfReader.getPdfObjectRelease(catalog.get(PdfName.OUTLINES));
277         if (obj == null || !obj.isDictionary())
278             return null;
279         PdfDictionary outlines = (PdfDictionary)obj;
280         IntHashtable pages = new IntHashtable();
281         int numPages = reader.getNumberOfPages();
282         for (int k = 1; k <= numPages; ++k) {
283             pages.put(reader.getPageOrigRef(k).getNumber(), k);
284             reader.releasePage(k);
285         }
286         return bookmarkDepth(reader, (PdfDictionary)PdfReader.getPdfObjectRelease(outlines.get(PdfName.FIRST)), pages);
287     }
288     
289     /**
290      * Removes the bookmark entries for a number of page ranges. The page ranges
291      * consists of a number of pairs with the start/end page range. The page numbers
292      * are inclusive.
293      * @param list the bookmarks
294      * @param pageRange the page ranges, always in pairs.
295      */

296     public static void eliminatePages(List JavaDoc list, int pageRange[]) {
297         if (list == null)
298             return;
299         for (Iterator JavaDoc it = list.listIterator(); it.hasNext();) {
300             HashMap JavaDoc map = (HashMap JavaDoc)it.next();
301             boolean hit = false;
302             if ("GoTo".equals(map.get("Action"))) {
303                 String JavaDoc page = (String JavaDoc)map.get("Page");
304                 if (page != null) {
305                     page = page.trim();
306                     int idx = page.indexOf(' ');
307                     int pageNum;
308                     if (idx < 0)
309                         pageNum = Integer.parseInt(page);
310                     else
311                         pageNum = Integer.parseInt(page.substring(0, idx));
312                     int len = pageRange.length & 0xfffffffe;
313                     for (int k = 0; k < len; k += 2) {
314                         if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
315                             hit = true;
316                             break;
317                         }
318                     }
319                 }
320             }
321             List JavaDoc kids = (List JavaDoc)map.get("Kids");
322             if (kids != null) {
323                 eliminatePages(kids, pageRange);
324                 if (kids.isEmpty()) {
325                     map.remove("Kids");
326                     kids = null;
327                 }
328             }
329             if (hit) {
330                 if (kids == null)
331                     it.remove();
332                 else {
333                     map.remove("Action");
334                     map.remove("Page");
335                     map.remove("Named");
336                 }
337             }
338         }
339     }
340     
341     /**
342      * For the pages in range add the <CODE>pageShift</CODE> to the page number.
343      * The page ranges
344      * consists of a number of pairs with the start/end page range. The page numbers
345      * are inclusive.
346      * @param list the bookmarks
347      * @param pageShift the number to add to the pages in range
348      * @param pageRange the page ranges, always in pairs. It can be <CODE>null</CODE>
349      * to include all the pages
350      */

351     public static void shiftPageNumbers(List JavaDoc list, int pageShift, int pageRange[]) {
352         if (list == null)
353             return;
354         for (Iterator JavaDoc it = list.listIterator(); it.hasNext();) {
355             HashMap JavaDoc map = (HashMap JavaDoc)it.next();
356             if ("GoTo".equals(map.get("Action"))) {
357                 String JavaDoc page = (String JavaDoc)map.get("Page");
358                 if (page != null) {
359                     page = page.trim();
360                     int idx = page.indexOf(' ');
361                     int pageNum;
362                     if (idx < 0)
363                         pageNum = Integer.parseInt(page);
364                     else
365                         pageNum = Integer.parseInt(page.substring(0, idx));
366                     boolean hit = false;
367                     if (pageRange == null)
368                         hit = true;
369                     else {
370                         int len = pageRange.length & 0xfffffffe;
371                         for (int k = 0; k < len; k += 2) {
372                             if (pageNum >= pageRange[k] && pageNum <= pageRange[k + 1]) {
373                                 hit = true;
374                                 break;
375                             }
376                         }
377                     }
378                     if (hit) {
379                         if (idx < 0)
380                             page = Integer.toString(pageNum + pageShift);
381                         else
382                             page = (pageNum + pageShift) + page.substring(idx);
383                     }
384                     map.put("Page", page);
385                 }
386             }
387             List JavaDoc kids = (List JavaDoc)map.get("Kids");
388             if (kids != null)
389                 shiftPageNumbers(kids, pageShift, pageRange);
390         }
391     }
392     
393     static void createOutlineAction(PdfDictionary outline, HashMap JavaDoc map, PdfWriter writer, boolean namedAsNames) {
394         try {
395             String JavaDoc action = (String JavaDoc)map.get("Action");
396             if ("GoTo".equals(action)) {
397                 String JavaDoc p;
398                 if ((p = (String JavaDoc)map.get("Named")) != null) {
399                     if (namedAsNames)
400                         outline.put(PdfName.DEST, new PdfName(p));
401                     else
402                         outline.put(PdfName.DEST, new PdfString(p, null));
403                 }
404                 else if ((p = (String JavaDoc)map.get("Page")) != null) {
405                     PdfArray ar = new PdfArray();
406                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(p);
407                     int n = Integer.parseInt(tk.nextToken());
408                     ar.add(writer.getPageReference(n));
409                     if (!tk.hasMoreTokens()) {
410                         ar.add(PdfName.XYZ);
411                         ar.add(new float[]{0, 10000, 0});
412                     }
413                     else {
414                         String JavaDoc fn = tk.nextToken();
415                         if (fn.startsWith("/"))
416                             fn = fn.substring(1);
417                         ar.add(new PdfName(fn));
418                         for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
419                             fn = tk.nextToken();
420                             if (fn.equals("null"))
421                                 ar.add(PdfNull.PDFNULL);
422                             else
423                                 ar.add(new PdfNumber(fn));
424                         }
425                     }
426                     outline.put(PdfName.DEST, ar);
427                 }
428             }
429             else if ("GoToR".equals(action)) {
430                 String JavaDoc p;
431                 PdfDictionary dic = new PdfDictionary();
432                 if ((p = (String JavaDoc)map.get("Named")) != null)
433                     dic.put(PdfName.D, new PdfString(p, null));
434                 else if ((p = (String JavaDoc)map.get("NamedN")) != null)
435                     dic.put(PdfName.D, new PdfName(p));
436                 else if ((p = (String JavaDoc)map.get("Page")) != null){
437                     PdfArray ar = new PdfArray();
438                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(p);
439                     ar.add(new PdfNumber(tk.nextToken()));
440                     if (!tk.hasMoreTokens()) {
441                         ar.add(PdfName.XYZ);
442                         ar.add(new float[]{0, 10000, 0});
443                     }
444                     else {
445                         String JavaDoc fn = tk.nextToken();
446                         if (fn.startsWith("/"))
447                             fn = fn.substring(1);
448                         ar.add(new PdfName(fn));
449                         for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
450                             fn = tk.nextToken();
451                             if (fn.equals("null"))
452                                 ar.add(PdfNull.PDFNULL);
453                             else
454                                 ar.add(new PdfNumber(fn));
455                         }
456                     }
457                     dic.put(PdfName.D, ar);
458                 }
459                 String JavaDoc file = (String JavaDoc)map.get("File");
460                 if (dic.size() > 0 && file != null) {
461                     dic.put(PdfName.S, PdfName.GOTOR);
462                     dic.put(PdfName.F, new PdfString(file));
463                     String JavaDoc nw = (String JavaDoc)map.get("NewWindow");
464                     if (nw != null) {
465                         if (nw.equals("true"))
466                             dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFTRUE);
467                         else if (nw.equals("false"))
468                             dic.put(PdfName.NEWWINDOW, PdfBoolean.PDFFALSE);
469                     }
470                     outline.put(PdfName.A, dic);
471                 }
472             }
473             else if ("URI".equals(action)) {
474                 String JavaDoc uri = (String JavaDoc)map.get("URI");
475                 if (uri != null) {
476                     PdfDictionary dic = new PdfDictionary();
477                     dic.put(PdfName.S, PdfName.URI);
478                     dic.put(PdfName.URI, new PdfString(uri));
479                     outline.put(PdfName.A, dic);
480                 }
481             }
482             else if ("Launch".equals(action)) {
483                 String JavaDoc file = (String JavaDoc)map.get("File");
484                 if (file != null) {
485                     PdfDictionary dic = new PdfDictionary();
486                     dic.put(PdfName.S, PdfName.LAUNCH);
487                     dic.put(PdfName.F, new PdfString(file));
488                     outline.put(PdfName.A, dic);
489                 }
490             }
491         }
492         catch (Exception JavaDoc e) {
493             // empty on purpose
494
}
495     }
496
497     public static Object JavaDoc[] iterateOutlines(PdfWriter writer, PdfIndirectReference parent, List JavaDoc kids, boolean namedAsNames) throws IOException JavaDoc {
498         PdfIndirectReference refs[] = new PdfIndirectReference[kids.size()];
499         for (int k = 0; k < refs.length; ++k)
500             refs[k] = writer.getPdfIndirectReference();
501         int ptr = 0;
502         int count = 0;
503         for (Iterator JavaDoc it = kids.listIterator(); it.hasNext(); ++ptr) {
504             HashMap JavaDoc map = (HashMap JavaDoc)it.next();
505             Object JavaDoc lower[] = null;
506             List JavaDoc subKid = (List JavaDoc)map.get("Kids");
507             if (subKid != null && !subKid.isEmpty())
508                 lower = iterateOutlines(writer, refs[ptr], subKid, namedAsNames);
509             PdfDictionary outline = new PdfDictionary();
510             ++count;
511             if (lower != null) {
512                 outline.put(PdfName.FIRST, (PdfIndirectReference)lower[0]);
513                 outline.put(PdfName.LAST, (PdfIndirectReference)lower[1]);
514                 int n = ((Integer JavaDoc)lower[2]).intValue();
515                 if ("false".equals(map.get("Open"))) {
516                     outline.put(PdfName.COUNT, new PdfNumber(-n));
517                 }
518                 else {
519                     outline.put(PdfName.COUNT, new PdfNumber(n));
520                     count += n;
521                 }
522             }
523             outline.put(PdfName.PARENT, parent);
524             if (ptr > 0)
525                 outline.put(PdfName.PREV, refs[ptr - 1]);
526             if (ptr < refs.length - 1)
527                 outline.put(PdfName.NEXT, refs[ptr + 1]);
528             outline.put(PdfName.TITLE, new PdfString((String JavaDoc)map.get("Title"), PdfObject.TEXT_UNICODE));
529             String JavaDoc color = (String JavaDoc)map.get("Color");
530             if (color != null) {
531                 try {
532                     PdfArray arr = new PdfArray();
533                     StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(color);
534                     for (int k = 0; k < 3; ++k) {
535                         float f = Float.parseFloat(tk.nextToken());
536                         if (f < 0) f = 0;
537                         if (f > 1) f = 1;
538                         arr.add(new PdfNumber(f));
539                     }
540                     outline.put(PdfName.C, arr);
541                 } catch(Exception JavaDoc e){} //in case it's malformed
542
}
543             String JavaDoc style = (String JavaDoc)map.get("Style");
544             if (style != null) {
545                 style = style.toLowerCase();
546                 int bits = 0;
547                 if (style.indexOf("italic") >= 0)
548                     bits |= 1;
549                 if (style.indexOf("bold") >= 0)
550                     bits |= 2;
551                 if (bits != 0)
552                     outline.put(PdfName.F, new PdfNumber(bits));
553             }
554             createOutlineAction(outline, map, writer, namedAsNames);
555             writer.addToBody(outline, refs[ptr]);
556         }
557         return new Object JavaDoc[]{refs[0], refs[refs.length - 1], new Integer JavaDoc(count)};
558     }
559     
560     /**
561      * Exports the bookmarks to XML. Only of use if the generation is to be include in
562      * some other XML document.
563      * @param list the bookmarks
564      * @param out the export destination. The writer is not closed
565      * @param indent the indentation level. Pretty printing significant only
566      * @param onlyASCII codes above 127 will always be escaped with &amp;#nn; if <CODE>true</CODE>,
567      * whatever the encoding
568      * @throws IOException on error
569      */

570     public static void exportToXMLNode(List JavaDoc list, Writer JavaDoc out, int indent, boolean onlyASCII) throws IOException JavaDoc {
571         String JavaDoc dep = "";
572         for (int k = 0; k < indent; ++k)
573             dep += " ";
574         for (Iterator JavaDoc it = list.iterator(); it.hasNext();) {
575             HashMap JavaDoc map = (HashMap JavaDoc)it.next();
576             String JavaDoc title = null;
577             out.write(dep);
578             out.write("<Title ");
579             List JavaDoc kids = null;
580             for (Iterator JavaDoc e = map.entrySet().iterator(); e.hasNext();) {
581                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) e.next();
582                 String JavaDoc key = (String JavaDoc) entry.getKey();
583                 if (key.equals("Title")) {
584                     title = (String JavaDoc) entry.getValue();
585                     continue;
586                 }
587                 else if (key.equals("Kids")) {
588                     kids = (List JavaDoc) entry.getValue();
589                     continue;
590                 }
591                 else {
592                     out.write(key);
593                     out.write("=\"");
594                     String JavaDoc value = (String JavaDoc) entry.getValue();
595                     if (key.equals("Named") || key.equals("NamedN"))
596                         value = SimpleNamedDestination.escapeBinaryString(value);
597                     out.write(SimpleXMLParser.escapeXML(value, onlyASCII));
598                     out.write("\" ");
599                 }
600             }
601             out.write(">");
602             if (title == null)
603                 title = "";
604             out.write(SimpleXMLParser.escapeXML(title, onlyASCII));
605             if (kids != null) {
606                 out.write("\n");
607                 exportToXMLNode(kids, out, indent + 1, onlyASCII);
608                 out.write(dep);
609             }
610             out.write("</Title>\n");
611         }
612     }
613     
614     /**
615      * Exports the bookmarks to XML. The DTD for this XML is:
616      * <p>
617      * <pre>
618      * &lt;?xml version='1.0' encoding='UTF-8'?&gt;
619      * &lt;!ELEMENT Title (#PCDATA|Title)*&gt;
620      * &lt;!ATTLIST Title
621      * Action CDATA #IMPLIED
622      * Open CDATA #IMPLIED
623      * Page CDATA #IMPLIED
624      * URI CDATA #IMPLIED
625      * File CDATA #IMPLIED
626      * Named CDATA #IMPLIED
627      * NamedN CDATA #IMPLIED
628      * NewWindow CDATA #IMPLIED
629      * Style CDATA #IMPLIED
630      * Color CDATA #IMPLIED
631      * &gt;
632      * &lt;!ELEMENT Bookmark (Title)*&gt;
633      * </pre>
634      * @param list the bookmarks
635      * @param out the export destination. The stream is not closed
636      * @param encoding the encoding according to IANA conventions
637      * @param onlyASCII codes above 127 will always be escaped with &amp;#nn; if <CODE>true</CODE>,
638      * whatever the encoding
639      * @throws IOException on error
640      */

641     public static void exportToXML(List JavaDoc list, OutputStream JavaDoc out, String JavaDoc encoding, boolean onlyASCII) throws IOException JavaDoc {
642         String JavaDoc jenc = IanaEncodings.getJavaEncoding(encoding);
643         Writer JavaDoc wrt = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(out, jenc));
644         exportToXML(list, wrt, encoding, onlyASCII);
645     }
646     
647     /**
648      * Exports the bookmarks to XML.
649      * @param list the bookmarks
650      * @param wrt the export destination. The writer is not closed
651      * @param encoding the encoding according to IANA conventions
652      * @param onlyASCII codes above 127 will always be escaped with &amp;#nn; if <CODE>true</CODE>,
653      * whatever the encoding
654      * @throws IOException on error
655      */

656     public static void exportToXML(List JavaDoc list, Writer JavaDoc wrt, String JavaDoc encoding, boolean onlyASCII) throws IOException JavaDoc {
657         wrt.write("<?xml version=\"1.0\" encoding=\"");
658         wrt.write(SimpleXMLParser.escapeXML(encoding, onlyASCII));
659         wrt.write("\"?>\n<Bookmark>\n");
660         exportToXMLNode(list, wrt, 1, onlyASCII);
661         wrt.write("</Bookmark>\n");
662         wrt.flush();
663     }
664     
665     /**
666      * Import the bookmarks from XML.
667      * @param in the XML source. The stream is not closed
668      * @throws IOException on error
669      * @return the bookmarks
670      */

671     public static List JavaDoc importFromXML(InputStream JavaDoc in) throws IOException JavaDoc {
672         SimpleBookmark book = new SimpleBookmark();
673         SimpleXMLParser.parse(book, in);
674         return book.topList;
675     }
676     
677     /**
678      * Import the bookmarks from XML.
679      * @param in the XML source. The reader is not closed
680      * @throws IOException on error
681      * @return the bookmarks
682      */

683     public static List JavaDoc importFromXML(Reader JavaDoc in) throws IOException JavaDoc {
684         SimpleBookmark book = new SimpleBookmark();
685         SimpleXMLParser.parse(book, in);
686         return book.topList;
687     }
688     
689     public void endDocument() {
690     }
691     
692     public void endElement(String JavaDoc tag) {
693         if (tag.equals("Bookmark")) {
694             if (attr.isEmpty())
695                 return;
696             else
697                 throw new RuntimeException JavaDoc("Bookmark end tag out of place.");
698         }
699         if (!tag.equals("Title"))
700             throw new RuntimeException JavaDoc("Invalid end tag - " + tag);
701         HashMap JavaDoc attributes = (HashMap JavaDoc)attr.pop();
702         String JavaDoc title = (String JavaDoc)attributes.get("Title");
703         attributes.put("Title", title.trim());
704         String JavaDoc named = (String JavaDoc)attributes.get("Named");
705         if (named != null)
706             attributes.put("Named", SimpleNamedDestination.unEscapeBinaryString(named));
707         named = (String JavaDoc)attributes.get("NamedN");
708         if (named != null)
709             attributes.put("NamedN", SimpleNamedDestination.unEscapeBinaryString(named));
710         if (attr.isEmpty())
711             topList.add(attributes);
712         else {
713             HashMap JavaDoc parent = (HashMap JavaDoc)attr.peek();
714             List JavaDoc kids = (List JavaDoc)parent.get("Kids");
715             if (kids == null) {
716                 kids = new ArrayList JavaDoc();
717                 parent.put("Kids", kids);
718             }
719             kids.add(attributes);
720         }
721     }
722     
723     public void startDocument() {
724     }
725     
726     public void startElement(String JavaDoc tag, HashMap JavaDoc h) {
727         if (topList == null) {
728             if (tag.equals("Bookmark")) {
729                 topList = new ArrayList JavaDoc();
730                 return;
731             }
732             else
733                 throw new RuntimeException JavaDoc("Root element is not Bookmark: " + tag);
734         }
735         if (!tag.equals("Title"))
736             throw new RuntimeException JavaDoc("Tag " + tag + " not allowed.");
737         HashMap JavaDoc attributes = new HashMap JavaDoc(h);
738         attributes.put("Title", "");
739         attributes.remove("Kids");
740         attr.push(attributes);
741     }
742     
743     public void text(String JavaDoc str) {
744         if (attr.isEmpty())
745             return;
746         HashMap JavaDoc attributes = (HashMap JavaDoc)attr.peek();
747         String JavaDoc title = (String JavaDoc)attributes.get("Title");
748         title += str;
749         attributes.put("Title", title);
750     }
751 }
752
Popular Tags