KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * Copyright 2004 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 package com.lowagie.text.pdf;
48
49 import java.io.BufferedWriter JavaDoc;
50 import java.io.IOException JavaDoc;
51 import java.io.InputStream JavaDoc;
52 import java.io.OutputStream JavaDoc;
53 import java.io.OutputStreamWriter JavaDoc;
54 import java.io.Reader JavaDoc;
55 import java.io.Writer JavaDoc;
56 import java.util.ArrayList JavaDoc;
57 import java.util.HashMap JavaDoc;
58 import java.util.Iterator JavaDoc;
59 import java.util.Map JavaDoc;
60 import java.util.StringTokenizer JavaDoc;
61
62 import com.lowagie.text.xml.simpleparser.IanaEncodings;
63 import com.lowagie.text.xml.simpleparser.SimpleXMLDocHandler;
64 import com.lowagie.text.xml.simpleparser.SimpleXMLParser;
65
66 /**
67  *
68  * @author Paulo Soares (psoares@consiste.pt)
69  */

70 public class SimpleNamedDestination implements SimpleXMLDocHandler {
71     
72     private HashMap JavaDoc xmlNames;
73     private HashMap JavaDoc xmlLast;
74
75     private SimpleNamedDestination() {
76     }
77     
78     public static HashMap JavaDoc getNamedDestination(PdfReader reader, boolean fromNames) {
79         IntHashtable pages = new IntHashtable();
80         int numPages = reader.getNumberOfPages();
81         for (int k = 1; k <= numPages; ++k)
82             pages.put(reader.getPageOrigRef(k).getNumber(), k);
83         HashMap JavaDoc names = fromNames ? reader.getNamedDestinationFromNames() : reader.getNamedDestinationFromStrings();
84         for (Iterator JavaDoc it = names.entrySet().iterator(); it.hasNext();) {
85             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
86             ArrayList JavaDoc arr = ((PdfArray)entry.getValue()).getArrayList();
87             StringBuffer JavaDoc s = new StringBuffer JavaDoc();
88             try {
89                 s.append(pages.get(((PdfIndirectReference)arr.get(0)).getNumber()));
90                 s.append(' ').append(arr.get(1).toString().substring(1));
91                 for (int k = 2; k < arr.size(); ++k)
92                     s.append(' ').append(arr.get(k).toString());
93                 entry.setValue(s.toString());
94             }
95             catch (Exception JavaDoc e) {
96                 it.remove();
97             }
98         }
99         return names;
100     }
101     
102     /**
103      * Exports the destinations to XML. The DTD for this XML is:
104      * <p>
105      * <pre>
106      * &lt;?xml version='1.0' encoding='UTF-8'?&gt;
107      * &lt;!ELEMENT Name (#PCDATA)&gt;
108      * &lt;!ATTLIST Name
109      * Page CDATA #IMPLIED
110      * &gt;
111      * &lt;!ELEMENT Destination (Name)*&gt;
112      * </pre>
113      * @param names the names
114      * @param out the export destination. The stream is not closed
115      * @param encoding the encoding according to IANA conventions
116      * @param onlyASCII codes above 127 will always be escaped with &amp;#nn; if <CODE>true</CODE>,
117      * whatever the encoding
118      * @throws IOException on error
119      */

120     public static void exportToXML(HashMap JavaDoc names, OutputStream JavaDoc out, String JavaDoc encoding, boolean onlyASCII) throws IOException JavaDoc {
121         String JavaDoc jenc = IanaEncodings.getJavaEncoding(encoding);
122         Writer JavaDoc wrt = new BufferedWriter JavaDoc(new OutputStreamWriter JavaDoc(out, jenc));
123         exportToXML(names, wrt, encoding, onlyASCII);
124     }
125     
126     /**
127      * Exports the destinations to XML.
128      * @param names the names
129      * @param wrt the export destination. The writer is not closed
130      * @param encoding the encoding according to IANA conventions
131      * @param onlyASCII codes above 127 will always be escaped with &amp;#nn; if <CODE>true</CODE>,
132      * whatever the encoding
133      * @throws IOException on error
134      */

135     public static void exportToXML(HashMap JavaDoc names, Writer JavaDoc wrt, String JavaDoc encoding, boolean onlyASCII) throws IOException JavaDoc {
136         wrt.write("<?xml version=\"1.0\" encoding=\"");
137         wrt.write(SimpleXMLParser.escapeXML(encoding, onlyASCII));
138         wrt.write("\"?>\n<Destination>\n");
139         for (Iterator JavaDoc it = names.entrySet().iterator(); it.hasNext();) {
140             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
141             String JavaDoc key = (String JavaDoc)entry.getKey();
142             String JavaDoc value = (String JavaDoc)entry.getValue();
143             wrt.write(" <Name Page=\"");
144             wrt.write(SimpleXMLParser.escapeXML(value, onlyASCII));
145             wrt.write("\">");
146             wrt.write(SimpleXMLParser.escapeXML(escapeBinaryString(key), onlyASCII));
147             wrt.write("</Name>\n");
148         }
149         wrt.write("</Destination>\n");
150         wrt.flush();
151     }
152     
153     /**
154      * Import the names from XML.
155      * @param in the XML source. The stream is not closed
156      * @throws IOException on error
157      * @return the names
158      */

159     public static HashMap JavaDoc importFromXML(InputStream JavaDoc in) throws IOException JavaDoc {
160         SimpleNamedDestination names = new SimpleNamedDestination();
161         SimpleXMLParser.parse(names, in);
162         return names.xmlNames;
163     }
164     
165     /**
166      * Import the names from XML.
167      * @param in the XML source. The reader is not closed
168      * @throws IOException on error
169      * @return the names
170      */

171     public static HashMap JavaDoc importFromXML(Reader JavaDoc in) throws IOException JavaDoc {
172         SimpleNamedDestination names = new SimpleNamedDestination();
173         SimpleXMLParser.parse(names, in);
174         return names.xmlNames;
175     }
176
177     static PdfArray createDestinationArray(String JavaDoc value, PdfWriter writer) {
178         PdfArray ar = new PdfArray();
179         StringTokenizer JavaDoc tk = new StringTokenizer JavaDoc(value);
180         int n = Integer.parseInt(tk.nextToken());
181         ar.add(writer.getPageReference(n));
182         if (!tk.hasMoreTokens()) {
183             ar.add(PdfName.XYZ);
184             ar.add(new float[]{0, 10000, 0});
185         }
186         else {
187             String JavaDoc fn = tk.nextToken();
188             if (fn.startsWith("/"))
189                 fn = fn.substring(1);
190             ar.add(new PdfName(fn));
191             for (int k = 0; k < 4 && tk.hasMoreTokens(); ++k) {
192                 fn = tk.nextToken();
193                 if (fn.equals("null"))
194                     ar.add(PdfNull.PDFNULL);
195                 else
196                     ar.add(new PdfNumber(fn));
197             }
198         }
199         return ar;
200     }
201     
202     public static PdfDictionary outputNamedDestinationAsNames(HashMap JavaDoc names, PdfWriter writer) {
203         PdfDictionary dic = new PdfDictionary();
204         for (Iterator JavaDoc it = names.entrySet().iterator(); it.hasNext();) {
205             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
206             try {
207                 String JavaDoc key = (String JavaDoc)entry.getKey();
208                 String JavaDoc value = (String JavaDoc)entry.getValue();
209                 PdfArray ar = createDestinationArray(value, writer);
210                 PdfName kn = new PdfName(key);
211                 dic.put(kn, ar);
212             }
213             catch (Exception JavaDoc e) {
214                 // empty on purpose
215
}
216         }
217         return dic;
218     }
219     
220     public static PdfDictionary outputNamedDestinationAsStrings(HashMap JavaDoc names, PdfWriter writer) throws IOException JavaDoc {
221         HashMap JavaDoc n2 = new HashMap JavaDoc(names);
222         for (Iterator JavaDoc it = n2.entrySet().iterator(); it.hasNext();) {
223             Map.Entry JavaDoc entry = (Map.Entry JavaDoc)it.next();
224             try {
225                 String JavaDoc value = (String JavaDoc)entry.getValue();
226                 PdfArray ar = createDestinationArray(value, writer);
227                 entry.setValue(writer.addToBody(ar).getIndirectReference());
228             }
229             catch (Exception JavaDoc e) {
230                 it.remove();
231             }
232         }
233         return PdfNameTree.writeTree(n2, writer);
234     }
235     
236     public static String JavaDoc escapeBinaryString(String JavaDoc s) {
237         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
238         char cc[] = s.toCharArray();
239         int len = cc.length;
240         for (int k = 0; k < len; ++k) {
241             char c = cc[k];
242             if (c < ' ') {
243                 buf.append('\\');
244                 String JavaDoc octal = "00" + Integer.toOctalString((int)c);
245                 buf.append(octal.substring(octal.length() - 3));
246             }
247             else if (c == '\\')
248                 buf.append("\\\\");
249             else
250                 buf.append(c);
251         }
252         return buf.toString();
253     }
254     
255     public static String JavaDoc unEscapeBinaryString(String JavaDoc s) {
256         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
257         char cc[] = s.toCharArray();
258         int len = cc.length;
259         for (int k = 0; k < len; ++k) {
260             char c = cc[k];
261             if (c == '\\') {
262                 if (++k >= len) {
263                     buf.append('\\');
264                     break;
265                 }
266                 c = cc[k];
267                 if (c >= '0' && c <= '7') {
268                     int n = c - '0';
269                     ++k;
270                     for (int j = 0; j < 2 && k < len; ++j) {
271                         c = cc[k];
272                         if (c >= '0' && c <= '7') {
273                             ++k;
274                             n = n * 8 + c - '0';
275                         }
276                         else {
277                             break;
278                         }
279                     }
280                     --k;
281                     buf.append((char)n);
282                 }
283                 else
284                     buf.append(c);
285             }
286             else
287                 buf.append(c);
288         }
289         return buf.toString();
290     }
291     
292     public void endDocument() {
293     }
294     
295     public void endElement(String JavaDoc tag) {
296         if (tag.equals("Destination")) {
297             if (xmlLast == null && xmlNames != null)
298                 return;
299             else
300                 throw new RuntimeException JavaDoc("Destination end tag out of place.");
301         }
302         if (!tag.equals("Name"))
303             throw new RuntimeException JavaDoc("Invalid end tag - " + tag);
304         if (xmlLast == null || xmlNames == null)
305             throw new RuntimeException JavaDoc("Name end tag out of place.");
306         if (!xmlLast.containsKey("Page"))
307             throw new RuntimeException JavaDoc("Page attribute missing.");
308         xmlNames.put(unEscapeBinaryString((String JavaDoc)xmlLast.get("Name")), xmlLast.get("Page"));
309         xmlLast = null;
310     }
311     
312     public void startDocument() {
313     }
314     
315     public void startElement(String JavaDoc tag, HashMap JavaDoc h) {
316         if (xmlNames == null) {
317             if (tag.equals("Destination")) {
318                 xmlNames = new HashMap JavaDoc();
319                 return;
320             }
321             else
322                 throw new RuntimeException JavaDoc("Root element is not Destination.");
323         }
324         if (!tag.equals("Name"))
325             throw new RuntimeException JavaDoc("Tag " + tag + " not allowed.");
326         if (xmlLast != null)
327             throw new RuntimeException JavaDoc("Nested tags are not allowed.");
328         xmlLast = new HashMap JavaDoc(h);
329         xmlLast.put("Name", "");
330     }
331     
332     public void text(String JavaDoc str) {
333         if (xmlLast == null)
334             return;
335         String JavaDoc name = (String JavaDoc)xmlLast.get("Name");
336         name += str;
337         xmlLast.put("Name", name);
338     }
339 }
Popular Tags