KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > etymon > pj > object > PjString


1 package com.etymon.pj.object;
2
3 import java.io.*;
4 import com.etymon.pj.exception.*;
5
6 /**
7    A representation of the PDF string type.
8    @author Nassib Nassar
9 */

10 public class PjString
11     extends PjObject {
12
13     /**
14        Creates a string object.
15        @param s the string value to initialize this object to.
16     */

17     public PjString(String JavaDoc s) {
18         _s = s;
19     }
20
21     /**
22        Returns the string value of this object.
23        @return the string value of this object.
24     */

25     public String JavaDoc getString() {
26         return _s;
27     }
28
29     /**
30        Writes this string to a stream in PDF format.
31        @param os the stream to write to.
32        @return the number of bytes written.
33        @exception IOException if an I/O error occurs.
34      */

35     public long writePdf(OutputStream os) throws IOException {
36         long z = 0;
37         int length = _s.length();
38         char c;
39         z = z + write(os, "(");
40         for (int x = 0; x < length; x++) {
41             c = _s.charAt(x);
42             switch (c) {
43             case '\n':
44                 z = z + write(os, "\\n");
45                 break;
46             case '\r':
47                 z = z + write(os, "\\r");
48                 break;
49             case '\t':
50                 z = z + write(os, "\\t");
51                 break;
52             case '\b':
53                 z = z + write(os, "\\b");
54                 break;
55             case '\f':
56                 z = z + write(os, "\\f");
57                 break;
58             case '\\':
59                 z = z + write(os, "\\\\");
60                 break;
61             case '(':
62                 z = z + write(os, "\\(");
63                 break;
64             case ')':
65                 z = z + write(os, "\\)");
66                 break;
67             default:
68                 z = z + write(os, c);
69             }
70         }
71         z = z + write(os, ")");
72         return z;
73     }
74
75     /**
76        Returns a deep copy of this object.
77        @return a deep copy of this object.
78     */

79     public Object JavaDoc clone() {
80         return this;
81     }
82
83     /**
84        Returns a string representation of this array in PDF format.
85        @return the string representation.
86     public String toString() {
87         int length = _s.length();
88         char c;
89         StringBuffer sb = new StringBuffer("(");
90         for (int x = 0; x < length; x++) {
91             c = _s.charAt(x);
92             switch (c) {
93             case '\n':
94                 sb.append("\\n");
95                 break;
96             case '\r':
97                 sb.append("\\r");
98                 break;
99             case '\t':
100                 sb.append("\\t");
101                 break;
102             case '\b':
103                 sb.append("\\b");
104                 break;
105             case '\f':
106                 sb.append("\\f");
107                 break;
108             case '\\':
109                 sb.append("\\\\");
110                 break;
111             case '(':
112                 sb.append("\\(");
113                 break;
114             case ')':
115                 sb.append("\\)");
116                 break;
117             default:
118                 if (Character.isISOControl(c)) {
119                     sb.append('\\');
120                     sb.append(Integer.toOctalString((int)c));
121                 } else {
122                     sb.append(c);
123                 }
124             }
125         }
126         sb.append(')');
127         return sb.toString();
128     }
129     */

130
131     /**
132        Converts a PDF-encoded string to a java String, which may
133        be then be used to initialize a PjString object.
134        @param pdfString the PDF-encoded string to be decoded.
135        @return the sequence of characters decoded from pdfString,
136        represented as a java String.
137        @exception PdfFormatException if pdfString is invalid PDF.
138     */

139     public static String JavaDoc decodePdf(String JavaDoc pdfString) throws PdfFormatException {
140         int length = pdfString.length();
141         if (length == 0) {
142             throw new PdfFormatException("'(' or '<' expected.", 0);
143         }
144         switch (pdfString.charAt(0)) {
145         case '(':
146             if (pdfString.charAt(length - 1) != ')') {
147                 throw new PdfFormatException("')' expected.", length);
148             }
149             return decodeEscapedString(pdfString);
150         case '<':
151             if (pdfString.charAt(length - 1) != '>') {
152                 throw new PdfFormatException("'>' expected.", length);
153             }
154             return decodeHexString(pdfString);
155         default:
156             throw new PdfFormatException("'(' or '<' expected.", 0);
157         }
158     }
159
160     /**
161        Decodes a PDF string enclosed in parentheses. This method
162        ignores the first and last characters of pdfString because
163        they are assumed to be matching parentheses.
164        @param pdfString the PDF-encoded string to be decoded.
165        @return the sequence of characters decoded from pdfString,
166        represented as a java String.
167        @exception PdfFormatException if invalid PDF encoding is
168        encountered in pdfString.
169     */

170     private static String JavaDoc decodeEscapedString(String JavaDoc pdfString) throws PdfFormatException {
171         int length = pdfString.length();
172         StringBuffer JavaDoc decodedString = new StringBuffer JavaDoc(length);
173         StringBuffer JavaDoc escapeString = new StringBuffer JavaDoc(4);
174         boolean escape = false;
175         char ch;
176         int x = 1;
177         while (x < (length - 1)) {
178             ch = pdfString.charAt(x);
179             if (ch == '\\') {
180                 if (escape == false) {
181                     // this is the beginning of an escape string
182
escape = true;
183                     escapeString.setLength(0);
184                 } else {
185                     // we're already escaped, so this must be the 2nd backslash in a row
186
decodedString.append('\\');
187                     escape = false;
188                 }
189             } else {
190                 if (escape == false) {
191                     // it's a normal character
192
decodedString.append(ch);
193                 } else {
194                     // this is part of an escaped sequence
195
if (escapeString.length() == 0) {
196                         // it's the beginning of the sequence!
197
switch (ch) {
198                         case 'n':
199                             decodedString.append('\n');
200                             escape = false;
201                             break;
202                         case 'r':
203                             decodedString.append('\r');
204                             escape = false;
205                             break;
206                         case 't':
207                             decodedString.append('\t');
208                             escape = false;
209                             break;
210                         case 'b':
211                             decodedString.append('\b');
212                             escape = false;
213                             break;
214                         case 'f':
215                             decodedString.append('\f');
216                             escape = false;
217                             break;
218                         case '\\':
219                             decodedString.append('\\');
220                             escape = false;
221                             break;
222                         case '(':
223                             decodedString.append('(');
224                             escape = false;
225                             break;
226                         case ')':
227                             decodedString.append(')');
228                             escape = false;
229                             break;
230                         case '0':
231                         case '1':
232                         case '2':
233                         case '3':
234                         case '4':
235                         case '5':
236                         case '6':
237                         case '7':
238                         case '8':
239                         case '9':
240                             escapeString.append(ch);
241                             break;
242                         default:
243                             // here we should throw a new
244
// PdfFormatException("Invalid escape character.", x);
245
// unfortunately, I ran this on a PDF file created using
246
// Acrobat PDFWriter 2.0 for Windows, and that file had
247
// solitary '\' characters in strings (in a file path in
248
// a /Creator field), which is incorrect,
249
// unless I am missing something.
250
// so we may need to be more forgiving;
251
// for now, if we reach this point, let's just treat the
252
// token as a backslash and exit escape mode.
253
decodedString.append('\\');
254                             escape = false;
255                             // roll back counter to reprocess this character
256
x--;
257                         }
258                     } else {
259                         // it's just another character in the sequence;
260
// so either it's an octal digit, or else we're
261
// back to non-escape mode
262
switch (ch) {
263                         case '0':
264                         case '1':
265                         case '2':
266                         case '3':
267                         case '4':
268                         case '5':
269                         case '6':
270                         case '7':
271                         case '8':
272                         case '9':
273                             // octal digit
274
/*
275                             if (escapeString.length() < 3) {
276                                 escapeString.append(ch);
277                                 break;
278                             }
279                             */

280                             int len = escapeString.length();
281                             if (len < 3) {
282                                 escapeString.append(ch);
283                             }
284                             if (len < 2) {
285                                 break;
286                             }
287                             // otherwise we continue into the default section...
288
// but first push the counter forward, so it doesn't
289
// roll back to the current character.
290
x++;
291                         default:
292                             // end of escape; we need to decode the octal token and move on
293
decodedString.append((char)
294                                 Integer.parseInt(escapeString.toString(), 8));
295                             escape = false;
296                             // roll back counter to reprocess this character
297
x--;
298                         }
299                     }
300                 }
301             }
302             x++;
303         }
304         return decodedString.toString();
305     }
306     
307     /**
308        Decodes a PDF hexadecimal string enclosed in angle
309        brackets. This method ignores the first and last
310        characters of pdfString because they are assumed to be
311        matching angle brackets.
312        @param pdfString the PDF-encoded string to be decoded.
313        @return the sequence of characters decoded from pdfString,
314        represented as a java String.
315        @exception PdfFormatException if invalid PDF encoding is
316        encountered in pdfString.
317     */

318     private static String JavaDoc decodeHexString(String JavaDoc pdfString) throws PdfFormatException {
319         int length = pdfString.length();
320         StringBuffer JavaDoc decodedString = new StringBuffer JavaDoc(length);
321         StringBuffer JavaDoc hexString = new StringBuffer JavaDoc(4);
322         char ch;
323         int x = 1;
324         while (x < (length - 1)) {
325             ch = pdfString.charAt(x);
326             // first make sure it is a hex digit
327
switch (Character.toUpperCase(ch)) {
328             case '0':
329             case '1':
330             case '2':
331             case '3':
332             case '4':
333             case '5':
334             case '6':
335             case '7':
336             case '8':
337             case '9':
338             case 'A':
339             case 'B':
340             case 'C':
341             case 'D':
342             case 'E':
343             case 'F':
344                 // good, it is a valid hex character
345
// we accumulate pairs in hexString
346
hexString.append(ch);
347                 // if this is the last character, then pad out hexString with a zero if needed
348
if ( (x == (length - 2)) && (hexString.length() == 1) ) {
349                     hexString.append('0');
350                 }
351                 // now, if we have a pair of digits, evaluate it and clear hexString
352
if (hexString.length() == 2) {
353                     decodedString.append((char)Integer.parseInt(hexString.toString(), 16));
354                     hexString.setLength(0);
355                 }
356                 break;
357             case ' ':
358             case '\t':
359             case '\r':
360             case '\n':
361             case '\f':
362                 // ignore whitespace
363
break;
364             default:
365                 throw new PdfFormatException("Hexadecimal digit expected.", x);
366             }
367             x++;
368         }
369         return decodedString.toString();
370     }
371     
372     /**
373        Compares two PjString objects for equality.
374        @param obj the reference object to compare to.
375        @return true if this object is the same as obj, false
376        otherwise. */

377     public boolean equals(Object JavaDoc obj) {
378         if (obj == null) {
379             return false;
380         }
381         if (obj instanceof PjString) {
382             return _s.equals(((PjString)obj)._s);
383         } else {
384             return false;
385         }
386     }
387     
388     private String JavaDoc _s;
389     
390 }
391
Popular Tags