001: /*
002: * $Id: DocWriter.java 2563 2007-02-01 14:43:07Z blowagie $
003: * $Name$
004: *
005: * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text;
052:
053: import java.io.BufferedOutputStream;
054: import java.io.IOException;
055: import java.io.OutputStream;
056: import java.util.Iterator;
057: import java.util.Properties;
058:
059: import com.lowagie.text.pdf.OutputStreamCounter;
060:
061: /**
062: * An abstract <CODE>Writer</CODE> class for documents.
063: * <P>
064: * <CODE>DocWriter</CODE> is the abstract class of several writers such
065: * as <CODE>PdfWriter</CODE> and <CODE>HtmlWriter</CODE>.
066: * A <CODE>DocWriter</CODE> can be added as a <CODE>DocListener</CODE>
067: * to a certain <CODE>Document</CODE> by getting an instance (see method
068: * <CODE>getInstance()</CODE> in the specific writer-classes).
069: * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE>
070: * will be written to the <CODE>OutputStream</CODE> of the listening
071: * <CODE>DocWriter</CODE>.
072: *
073: * @see Document
074: * @see DocListener
075: */
076:
077: public abstract class DocWriter implements DocListener {
078:
079: /** This is some byte that is often used. */
080: public static final byte NEWLINE = (byte) '\n';
081:
082: /** This is some byte that is often used. */
083: public static final byte TAB = (byte) '\t';
084:
085: /** This is some byte that is often used. */
086: public static final byte LT = (byte) '<';
087:
088: /** This is some byte that is often used. */
089: public static final byte SPACE = (byte) ' ';
090:
091: /** This is some byte that is often used. */
092: public static final byte EQUALS = (byte) '=';
093:
094: /** This is some byte that is often used. */
095: public static final byte QUOTE = (byte) '\"';
096:
097: /** This is some byte that is often used. */
098: public static final byte GT = (byte) '>';
099:
100: /** This is some byte that is often used. */
101: public static final byte FORWARD = (byte) '/';
102:
103: // membervariables
104:
105: /** The pageSize. */
106: protected Rectangle pageSize;
107:
108: /** This is the document that has to be written. */
109: protected Document document;
110:
111: /** The outputstream of this writer. */
112: protected OutputStreamCounter os;
113:
114: /** Is the writer open for writing? */
115: protected boolean open = false;
116:
117: /** Do we have to pause all writing actions? */
118: protected boolean pause = false;
119:
120: /** Closes the stream on document close */
121: protected boolean closeStream = true;
122:
123: // constructor
124:
125: protected DocWriter() {
126: }
127:
128: /**
129: * Constructs a <CODE>DocWriter</CODE>.
130: *
131: * @param document The <CODE>Document</CODE> that has to be written
132: * @param os The <CODE>OutputStream</CODE> the writer has to write to.
133: */
134:
135: protected DocWriter(Document document, OutputStream os) {
136: this .document = document;
137: this .os = new OutputStreamCounter(new BufferedOutputStream(os));
138: }
139:
140: // implementation of the DocListener methods
141:
142: /**
143: * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>.
144: * <P>
145: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
146: * derived from this abstract class.
147: *
148: * @param element A high level object to add
149: * @return <CODE>false</CODE>
150: * @throws DocumentException when a document isn't open yet, or has been closed
151: */
152:
153: public boolean add(Element element) throws DocumentException {
154: return false;
155: }
156:
157: /**
158: * Signals that the <CODE>Document</CODE> was opened.
159: */
160:
161: public void open() {
162: open = true;
163: }
164:
165: /**
166: * Sets the pagesize.
167: *
168: * @param pageSize the new pagesize
169: * @return a <CODE>boolean</CODE>
170: */
171:
172: public boolean setPageSize(Rectangle pageSize) {
173: this .pageSize = pageSize;
174: return true;
175: }
176:
177: /**
178: * Sets the margins.
179: * <P>
180: * This does nothing. Has to be overridden if needed.
181: *
182: * @param marginLeft the margin on the left
183: * @param marginRight the margin on the right
184: * @param marginTop the margin on the top
185: * @param marginBottom the margin on the bottom
186: * @return <CODE>false</CODE>
187: */
188:
189: public boolean setMargins(float marginLeft, float marginRight,
190: float marginTop, float marginBottom) {
191: return false;
192: }
193:
194: /**
195: * Signals that an new page has to be started.
196: * <P>
197: * This does nothing. Has to be overridden if needed.
198: *
199: * @return <CODE>true</CODE> if the page was added, <CODE>false</CODE> if not.
200: * @throws DocumentException when a document isn't open yet, or has been closed
201: */
202:
203: public boolean newPage() {
204: if (!open) {
205: return false;
206: }
207: return true;
208: }
209:
210: /**
211: * Changes the header of this document.
212: * <P>
213: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
214: * derived from this abstract class if they actually support the use of
215: * headers.
216: *
217: * @param header the new header
218: */
219:
220: public void setHeader(HeaderFooter header) {
221: }
222:
223: /**
224: * Resets the header of this document.
225: * <P>
226: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
227: * derived from this abstract class if they actually support the use of
228: * headers.
229: */
230:
231: public void resetHeader() {
232: }
233:
234: /**
235: * Changes the footer of this document.
236: * <P>
237: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
238: * derived from this abstract class if they actually support the use of
239: * footers.
240: *
241: * @param footer the new footer
242: */
243:
244: public void setFooter(HeaderFooter footer) {
245: }
246:
247: /**
248: * Resets the footer of this document.
249: * <P>
250: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
251: * derived from this abstract class if they actually support the use of
252: * footers.
253: */
254:
255: public void resetFooter() {
256: }
257:
258: /**
259: * Sets the page number to 0.
260: * <P>
261: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
262: * derived from this abstract class if they actually support the use of
263: * pagenumbers.
264: */
265:
266: public void resetPageCount() {
267: }
268:
269: /**
270: * Sets the page number.
271: * <P>
272: * This method should be overriden in the specific <CODE>DocWriter<CODE> classes
273: * derived from this abstract class if they actually support the use of
274: * pagenumbers.
275: *
276: * @param pageN the new page number
277: */
278:
279: public void setPageCount(int pageN) {
280: }
281:
282: /**
283: * Signals that the <CODE>Document</CODE> was closed and that no other
284: * <CODE>Elements</CODE> will be added.
285: */
286:
287: public void close() {
288: open = false;
289: try {
290: os.flush();
291: if (closeStream)
292: os.close();
293: } catch (IOException ioe) {
294: throw new ExceptionConverter(ioe);
295: }
296: }
297:
298: // methods
299:
300: /** Converts a <CODE>String</CODE> into a <CODE>Byte</CODE> array
301: * according to the ISO-8859-1 codepage.
302: * @param text the text to be converted
303: * @return the conversion result
304: */
305:
306: public static final byte[] getISOBytes(String text) {
307: if (text == null)
308: return null;
309: int len = text.length();
310: byte b[] = new byte[len];
311: for (int k = 0; k < len; ++k)
312: b[k] = (byte) text.charAt(k);
313: return b;
314: }
315:
316: /**
317: * Let the writer know that all writing has to be paused.
318: */
319:
320: public void pause() {
321: pause = true;
322: }
323:
324: /**
325: * Checks if writing is paused.
326: *
327: * @return <CODE>true</CODE> if writing temporarely has to be paused, <CODE>false</CODE> otherwise.
328: */
329:
330: public boolean isPaused() {
331: return pause;
332: }
333:
334: /**
335: * Let the writer know that writing may be resumed.
336: */
337:
338: public void resume() {
339: pause = false;
340: }
341:
342: /**
343: * Flushes the <CODE>BufferedOutputStream</CODE>.
344: */
345:
346: public void flush() {
347: try {
348: os.flush();
349: } catch (IOException ioe) {
350: throw new ExceptionConverter(ioe);
351: }
352: }
353:
354: /**
355: * Writes a <CODE>String</CODE> to the <CODE>OutputStream</CODE>.
356: *
357: * @param string the <CODE>String</CODE> to write
358: * @throws IOException
359: */
360:
361: protected void write(String string) throws IOException {
362: os.write(getISOBytes(string));
363: }
364:
365: /**
366: * Writes a number of tabs.
367: *
368: * @param indent the number of tabs to add
369: * @throws IOException
370: */
371:
372: protected void addTabs(int indent) throws IOException {
373: os.write(NEWLINE);
374: for (int i = 0; i < indent; i++) {
375: os.write(TAB);
376: }
377: }
378:
379: /**
380: * Writes a key-value pair to the outputstream.
381: *
382: * @param key the name of an attribute
383: * @param value the value of an attribute
384: * @throws IOException
385: */
386:
387: protected void write(String key, String value) throws IOException {
388: os.write(SPACE);
389: write(key);
390: os.write(EQUALS);
391: os.write(QUOTE);
392: write(value);
393: os.write(QUOTE);
394: }
395:
396: /**
397: * Writes a starttag to the outputstream.
398: *
399: * @param tag the name of the tag
400: * @throws IOException
401: */
402:
403: protected void writeStart(String tag) throws IOException {
404: os.write(LT);
405: write(tag);
406: }
407:
408: /**
409: * Writes an endtag to the outputstream.
410: *
411: * @param tag the name of the tag
412: * @throws IOException
413: */
414:
415: protected void writeEnd(String tag) throws IOException {
416: os.write(LT);
417: os.write(FORWARD);
418: write(tag);
419: os.write(GT);
420: }
421:
422: /**
423: * Writes an endtag to the outputstream.
424: * @throws IOException
425: */
426:
427: protected void writeEnd() throws IOException {
428: os.write(SPACE);
429: os.write(FORWARD);
430: os.write(GT);
431: }
432:
433: /**
434: * Writes the markup attributes of the specified <CODE>MarkupAttributes</CODE>
435: * object to the <CODE>OutputStream</CODE>.
436: * @param markup a <CODE>Properties</CODE> collection to write.
437: * @return true, if writing the markup attributes succeeded
438: * @throws IOException
439: */
440: protected boolean writeMarkupAttributes(Properties markup)
441: throws IOException {
442: if (markup == null)
443: return false;
444: Iterator attributeIterator = markup.keySet().iterator();
445: String name;
446: while (attributeIterator.hasNext()) {
447: name = String.valueOf(attributeIterator.next());
448: write(name, markup.getProperty(name));
449: }
450: markup.clear();
451: return true;
452: }
453:
454: /** Checks if the stream is to be closed on document close
455: * @return true if the stream is closed on documnt close
456: *
457: */
458: public boolean isCloseStream() {
459: return closeStream;
460: }
461:
462: /** Sets the close state of the stream after document close
463: * @param closeStream true if the stream is closed on document close
464: *
465: */
466: public void setCloseStream(boolean closeStream) {
467: this .closeStream = closeStream;
468: }
469:
470: /**
471: * @see com.lowagie.text.DocListener#setMarginMirroring(boolean)
472: */
473: public boolean setMarginMirroring(boolean MarginMirroring) {
474: return false;
475: }
476:
477: }
|