KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > rtf > document > RtfDocument


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

50
51 package com.lowagie.text.rtf.document;
52
53 import java.io.IOException JavaDoc;
54 import java.io.OutputStream JavaDoc;
55 import java.util.ArrayList JavaDoc;
56
57 import com.lowagie.text.rtf.RtfBasicElement;
58 import com.lowagie.text.rtf.RtfElement;
59 import com.lowagie.text.rtf.RtfMapper;
60 import com.lowagie.text.rtf.document.output.*;
61 import com.lowagie.text.rtf.graphic.RtfImage;
62
63 /**
64  * The RtfDocument stores all document related data and also the main data stream.
65  * INTERNAL CLASS - NOT TO BE USED DIRECTLY
66  *
67  * @version $Id: RtfDocument.java 2808 2007-05-30 10:58:16Z psoares33 $
68  * @author Mark Hall (mhall@edu.uni-klu.ac.at)
69  * @author Todd Bush [Tab support]
70  * @author Thomas Bickel (tmb99@inode.at)
71  */

72 public class RtfDocument extends RtfElement {
73     /**
74      * Stores the actual document data
75      */

76     private RtfDataCache data = null;
77     /**
78      * The RtfMapper to use in this RtfDocument
79      */

80     private RtfMapper mapper = null;
81     /**
82      * The RtfDocumentHeader that handles all document header methods
83      */

84     private RtfDocumentHeader documentHeader = null;
85     /**
86      * Stores integers that have been generated as unique random numbers
87      */

88     private ArrayList JavaDoc previousRandomInts = null;
89     /**
90      * Whether to automatically generate TOC entries for Chapters and Sections. Defaults to false
91      */

92     private boolean autogenerateTOCEntries = false;
93     /**
94      * The RtfDocumentSettings for this RtfDocument.
95      */

96     private RtfDocumentSettings documentSettings = null;
97     /**
98      * The last RtfBasicElement that was added directly to the RtfDocument.
99      */

100     private RtfBasicElement lastElementWritten = null;
101     
102     /**
103      * Constant for the Rtf document start
104      */

105     private static final byte[] RTF_DOCUMENT = "\\rtf1".getBytes();
106
107     private final static byte[] FSC_LINE = "\\line ".getBytes();
108     private final static byte[] FSC_PAR = "\\par ".getBytes();
109     private final static byte[] FSC_TAB = "\\tab ".getBytes();
110     private final static byte[] FSC_PAGE_PAR = "\\page\\par ".getBytes();
111     private final static byte[] FSC_NEWPAGE = "$newpage$".getBytes();
112     private final static byte[] FSC_BACKSLASH = "\\".getBytes();
113     private final static byte[] FSC_HEX_PREFIX = "\\\'".getBytes();
114     private final static byte[] FSC_UNI_PREFIX = "\\u".getBytes();
115     
116     /**
117      * The default constructor for a RtfDocument
118      */

119     public RtfDocument() {
120         super(null);
121         this.data = new RtfMemoryCache();
122         this.mapper = new RtfMapper(this);
123         this.documentHeader = new RtfDocumentHeader(this);
124         this.documentHeader.init();
125         this.previousRandomInts = new ArrayList JavaDoc();
126         this.documentSettings = new RtfDocumentSettings(this);
127     }
128
129     /**
130      * unused
131      * @deprecated replaced by {@link #writeContent(OutputStream)}
132      */

133     public byte[] write()
134     {
135         return(new byte[0]);
136     }
137     /**
138      * unused
139      */

140     public void writeContent(final OutputStream JavaDoc out) throws IOException JavaDoc
141     {
142     }
143     
144     /**
145      * Writes the document
146      *
147      * @param out The <code>OutputStream</code> to write the RTF document to.
148      */

149     public void writeDocument(OutputStream JavaDoc out) {
150         try {
151             out.write(OPEN_GROUP);
152             out.write(RtfDocument.RTF_DOCUMENT);
153             //out.write(documentHeader.write());
154
this.documentHeader.writeContent(out);
155             this.data.writeTo(out);
156             out.write(CLOSE_GROUP);
157         } catch(IOException JavaDoc ioe) {
158             ioe.printStackTrace();
159         }
160     }
161     
162     /**
163      * Opens the RtfDocument and initialises the data cache. If the data cache is
164      * set to CACHE_DISK, but the cache cannot be initialised then the memory cache
165      * is used.
166      */

167     public void open() {
168         try {
169             switch(this.documentSettings.getDataCacheStyle()) {
170                 case RtfDataCache.CACHE_MEMORY_EFFICIENT:
171                     this.data = new RtfEfficientMemoryCache();
172                     break;
173                 case RtfDataCache.CACHE_MEMORY:
174                     this.data = new RtfMemoryCache();
175                     break;
176                 case RtfDataCache.CACHE_DISK:
177                     this.data = new RtfDiskCache();
178                     break;
179                 default:
180                     throw(new RuntimeException JavaDoc("unknown"));
181             }
182             
183         } catch(IOException JavaDoc ioe) {
184             System.err.println("Could not initialise disk cache. Using memory cache.");
185             ioe.printStackTrace();
186             this.data = new RtfMemoryCache();
187         }
188     }
189     
190     /**
191      * Adds an element to the rtf document
192      *
193      * @param element The element to add
194      */

195     public void add(RtfBasicElement element) {
196         try {
197             if(element instanceof RtfInfoElement) {
198                 this.documentHeader.addInfoElement((RtfInfoElement) element);
199             } else {
200                 if(element instanceof RtfImage) {
201                     ((RtfImage) element).setTopLevelElement(true);
202                 }
203                 element.writeContent( this.data.getOutputStream() );
204                 this.lastElementWritten = element;
205             }
206         } catch(IOException JavaDoc ioe) {
207             ioe.printStackTrace();
208         }
209     }
210     
211     /**
212      * Gets the RtfMapper object of this RtfDocument
213      *
214      * @return The RtfMapper
215      */

216     public RtfMapper getMapper() {
217         return this.mapper;
218     }
219     
220     /**
221      * Generates a random integer that is unique with respect to the document.
222      *
223      * @return A random int
224      */

225     public int getRandomInt() {
226         Integer JavaDoc newInt = null;
227         do {
228             newInt = new Integer JavaDoc((int) (Math.random() * Integer.MAX_VALUE));
229         } while(this.previousRandomInts.contains(newInt));
230         this.previousRandomInts.add(newInt);
231         return newInt.intValue();
232     }
233     
234     /**
235      * Gets the RtfDocumentHeader of this RtfDocument
236      *
237      * @return The RtfDocumentHeader of this RtfDocument
238      */

239     public RtfDocumentHeader getDocumentHeader() {
240         return this.documentHeader;
241     }
242     
243     /**
244      * Replaces special characters with their unicode values
245      * @param str The original <code>String</code>
246      * @param useHex indicated if the hexadecimal value has to be used
247      * @param softLineBreaks whether to use soft line breaks instead of default hard ones.
248      *
249      * @deprecated replaced by {@link #filterSpecialChar(OutputStream, String, boolean, boolean)}
250      * @return The converted String
251      */

252     public String JavaDoc filterSpecialChar(String JavaDoc str, boolean useHex, boolean softLineBreaks) {
253         if(str == null) {
254             return "";
255         }
256         int length = str.length();
257         int z = 'z';
258         StringBuffer JavaDoc ret = new StringBuffer JavaDoc(length);
259         for (int i = 0; i < length; i++) {
260             char ch = str.charAt(i);
261
262             if (ch == '\\') {
263                 ret.append("\\\\");
264             } else if (ch == '\n') {
265                 if(softLineBreaks) {
266                     ret.append("\\line ");
267                 } else {
268                     ret.append("\\par ");
269                 }
270             } else if (ch == '\t') {
271                 ret.append("\\tab ");
272             } else if ((ch) > z && this.documentSettings.isAlwaysUseUnicode()) {
273                 if(useHex) {
274                     ret.append("\\\'").append(Long.toHexString(ch));
275                 } else {
276                     ret.append("\\u").append((long) ch).append('?');
277                 }
278             } else {
279                 ret.append(ch);
280             }
281         }
282         String JavaDoc s = ret.toString();
283         if(s.indexOf("$newpage$") >= 0) {
284             String JavaDoc before = s.substring(0, s.indexOf("$newpage$"));
285             String JavaDoc after = s.substring(s.indexOf("$newpage$") + 9);
286             ret = new StringBuffer JavaDoc(before);
287             ret.append("\\page\\par ");
288             ret.append(after);
289             return ret.toString();
290         }
291         return s;
292     }
293     
294     /**
295      * Writes the given string to the given {@link OutputStream} encoding the string characters.
296      *
297      * @param out destination OutputStream
298      * @param str string to write
299      * @param useHex if <code>true</code> hex encoding characters is preferred to unicode encoding if possible
300      * @param softLineBreaks if <code>true</code> return characters are written as soft line breaks
301      *
302      * @throws IOException
303      */

304     public void filterSpecialChar(final OutputStream JavaDoc out, final String JavaDoc str, final boolean useHex, final boolean softLineBreaks) throws IOException JavaDoc
305     {
306         if(out == null) {
307             throw(new NullPointerException JavaDoc("null OutpuStream"));
308         }
309
310         final boolean alwaysUseUniCode = this.documentSettings.isAlwaysUseUnicode();
311         if(str == null) {
312             return;
313         }
314         final int len = str.length();
315         if(len == 0) {
316             return;
317         }
318
319         for(int k = 0; k < len; k++) {
320             final char c = str.charAt(k);
321             if(c < 0x20) {
322                 //allow return and tab only
323
if(c == '\n') {
324                     out.write(softLineBreaks ? FSC_LINE : FSC_PAR);
325                 } else
326                     if(c == '\t') {
327                         out.write(FSC_TAB);
328                     } else {
329                         out.write('?');
330                     }
331             } else
332                 if((c == '\\') || (c == '{') || (c == '}')) {
333                     //escape
334
out.write(FSC_BACKSLASH);
335                     out.write(c);
336                 } else
337                     if((c == '$') && (len-k >= FSC_NEWPAGE.length) && subMatch(str, k, FSC_NEWPAGE)) {
338                         //"$newpage$" -> "\\page\\par "
339
out.write(FSC_PAGE_PAR);
340                         k += FSC_NEWPAGE.length-1;
341                     } else {
342                         if((c > 0xff) || ((c > 'z') && alwaysUseUniCode)) {
343                             if(useHex && (c <= 0xff)) {
344                                 //encode as 2 char hex string
345
out.write(FSC_HEX_PREFIX);
346                                 out.write(RtfImage.byte2charLUT, c*2, 2);
347                             } else {
348                                 //encode as decimal, signed short value
349
out.write(FSC_UNI_PREFIX);
350                                 String JavaDoc s = Short.toString((short)c);
351                                 for(int x = 0; x < s.length(); x++) {
352                                     out.write(s.charAt(x));
353                                 }
354                                 out.write('?');
355                             }
356                         } else {
357                             out.write(c);
358                         }
359                     }
360         }
361     }
362     /**
363      * Returns <code>true</code> if <tt>m.length</tt> characters in <tt>str</tt>, starting at offset <tt>soff</tt>
364      * match the bytes in the given array <tt>m</tt>.
365      *
366      * @param str the string to search for a match
367      * @param soff the starting offset in str
368      * @param m the array to match
369      * @return <code>true</code> if there is match
370      */

371     private static boolean subMatch(final String JavaDoc str, int soff, final byte[] m)
372     {
373         for(int k = 0; k < m.length; k++) {
374             if(str.charAt(soff++) != m[k]) {
375                 return(false);
376             }
377         }
378         return(true);
379     }
380     
381     /**
382      * Whether to automagically generate table of contents entries when
383      * adding Chapters or Sections.
384      *
385      * @param autogenerate Whether to automatically generate TOC entries
386      */

387     public void setAutogenerateTOCEntries(boolean autogenerate) {
388         this.autogenerateTOCEntries = autogenerate;
389     }
390     
391     /**
392      * Get whether to autmatically generate table of contents entries
393      *
394      * @return Wheter to automatically generate TOC entries
395      */

396     public boolean getAutogenerateTOCEntries() {
397         return this.autogenerateTOCEntries;
398     }
399     
400     /**
401      * Gets the RtfDocumentSettings that specify how the rtf document is generated.
402      *
403      * @return The current RtfDocumentSettings.
404      */

405     public RtfDocumentSettings getDocumentSettings() {
406         return this.documentSettings;
407     }
408     
409     /**
410      * Gets the last RtfBasicElement that was directly added to the RtfDocument.
411      *
412      * @return The last RtfBasicElement that was directly added to the RtfDocument.
413      */

414     public RtfBasicElement getLastElementWritten() {
415         return this.lastElementWritten;
416     }
417 }
Popular Tags