KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > xml > xmlc > codegen > IndentWriter


1 /*
2  * Enhydra Java Application Server Project
3  *
4  * The contents of this file are subject to the Enhydra Public License
5  * Version 1.1 (the "License"); you may not use this file except in
6  * compliance with the License. You may obtain a copy of the License on
7  * the Enhydra web site ( http://www.enhydra.org/ ).
8  *
9  * Software distributed under the License is distributed on an "AS IS"
10  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11  * the License for the specific terms governing rights and limitations
12  * under the License.
13  *
14  * The Initial Developer of the Enhydra Application Server is Lutris
15  * Technologies, Inc. The Enhydra Application Server and portions created
16  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
17  * All Rights Reserved.
18  *
19  * Contributor(s):
20  *
21  * $Id: IndentWriter.java,v 1.2 2005/01/26 08:29:24 jkjome Exp $
22  */

23
24 package org.enhydra.xml.xmlc.codegen;
25
26 import java.io.BufferedOutputStream JavaDoc;
27 import java.io.File JavaDoc;
28 import java.io.FileOutputStream JavaDoc;
29 import java.io.IOException JavaDoc;
30 import java.io.OutputStreamWriter JavaDoc;
31 import java.io.PrintWriter JavaDoc;
32 import java.io.Writer JavaDoc;
33 import java.util.ArrayList JavaDoc;
34
35 import org.enhydra.xml.xmlc.XMLCError;
36
37 /**
38  * Class to print lines with indentation. Overrides all print methods
39  * to do indentation at the start of a line.
40  */

41 public class IndentWriter extends PrintWriter JavaDoc {
42     /*
43      * Are we at the beginning of the line.
44      */

45     private boolean fAtBOLN = true;
46     
47     /**
48      * Standard indentation amount.
49      */

50     private static int INDENT_SIZE = 4;
51
52     /**
53      * Current indentation level (in characters units).
54      */

55     private int fIndent = 0;
56
57     /**
58      * Stack of additional indentation that has
59      */

60     private int fAdditionalIndent = 0;
61
62     /**
63      * Stack of additional indentation amounts that have been
64      * added (entries are Integer).
65      */

66     private ArrayList JavaDoc fAdditionalIndentStack;
67
68     /**
69      * Generate an error if indentation is not zero on close.
70      */

71     private boolean fZeroCheck = true;
72
73     /**
74      * Current indentation prefix.
75      */

76     private String JavaDoc fIndentPrefix = "";
77     
78     /**
79      * Static string that is used as a quick way to get a certain indent
80      * level. Indent strings are generated by taking substrings of this
81      * string. This string is grown as needed.
82      */

83     private static String JavaDoc fIndentSourceString
84         = " ";
85
86     /**
87      * Constructor from a Writer
88      */

89     public IndentWriter(Writer JavaDoc writer) {
90         super(writer);
91     }
92
93     /**
94      * Constructor from a Writer
95      */

96     public IndentWriter(Writer JavaDoc writer,
97                         boolean autoflush) {
98         super(writer, autoflush);
99     }
100
101     /**
102      * Set value of zero-check flag. If true, then generate an error if
103      * indentation is not zero on close. Default is true.
104      */

105     public void setZeroCheck(boolean value) {
106         fZeroCheck = value;
107     }
108
109     /**
110      * Get value of zero-check flag.
111      */

112     public boolean getZeroCheck() {
113         return fZeroCheck;
114     }
115
116     /**
117      * Utility to open file.
118      */

119     private static Writer JavaDoc openFile(File JavaDoc src, String JavaDoc enc) throws IOException JavaDoc {
120         // Create directory if it doesn't exist
121
String JavaDoc parent = src.getParent();
122         if (parent != null) {
123             new File JavaDoc(parent).mkdirs();
124         }
125     if (enc == null) {
126             return new PrintWriter JavaDoc(new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(src)));
127     } else {
128             return new PrintWriter JavaDoc(new OutputStreamWriter JavaDoc(
129             new BufferedOutputStream JavaDoc(new FileOutputStream JavaDoc(src)), enc));
130     }
131         
132
133     }
134
135     /**
136      * Constructor given a file name. If the directory containing
137      * the file doesn't exist, it is created.
138      */

139     public IndentWriter(File JavaDoc src) throws IOException JavaDoc {
140         super(openFile(src, null));
141     }
142
143     /**
144      * Constructor given a file name and an encoding. If the directory containing
145      * the file doesn't exist, it is created.
146      */

147     public IndentWriter(File JavaDoc src, String JavaDoc enc) throws IOException JavaDoc {
148         super(openFile(src, enc));
149     }
150
151     /**
152      * Called when through generating code. Close the contained stream and
153      * make sure that indentation is zero. If not, we might have screawed
154      * something up.
155      * @param ignoreErrors If true, ignore any errors and don't check
156      * for zero. This should be used only when calling this method while
157      * handling an error.
158      */

159     public void close(boolean ignoreErrors) {
160         if (ignoreErrors) {
161             try {
162                 super.close();
163             } catch (Throwable JavaDoc err) {
164                 // ignore
165
}
166         } else {
167             super.close();
168             checkZero();
169         }
170     }
171
172     /**
173      * Flush output; indentation must be zero.
174      */

175     public void flush() {
176         super.flush();
177         checkZero();
178     }
179
180     /**
181      * Get an indentation from the source string, growing source as needed.
182      */

183     private static String JavaDoc getIndentString(int numChars) {
184         // Grow if needed; coded to avoid sync
185
while (fIndentSourceString.length() < numChars) {
186             fIndentSourceString += fIndentSourceString;
187         }
188         return fIndentSourceString.substring(0, numChars);
189     }
190
191     /**
192      * Set the current indentation string.
193      */

194     private void setIndentPrefix() {
195         fIndentPrefix = getIndentString(fIndent);
196     }
197
198     /**
199      * Check that the indentation is zero.
200      */

201     private void checkZero() {
202         if (fZeroCheck && (fIndent != 0)) {
203             // This could indicate something more serious.
204
throw new XMLCError("code indentation not zero at end");
205         }
206     }
207
208     /**
209      * Increase indentation level.
210      */

211     public final void enter() {
212         fIndent += INDENT_SIZE;
213         setIndentPrefix();
214     }
215
216     /**
217      * Decrease indentation level.
218      */

219     public final void leave() {
220         fIndent -= INDENT_SIZE;
221         if (fIndent < 0) {
222             throw new XMLCError("identation level underflow");
223         }
224         setIndentPrefix();
225     }
226
227     /**
228      * Get the indentation level.
229      */

230     public final int getIndentLevel() {
231         return fIndent;
232     }
233
234     /**
235      * Push an additional amount of indentation, in an arbitrary number of
236      * characters. This is used for aligning parameters, etc, which
237      * don't fall on the block-level indent boundry.
238      */

239     final public void pushAdditionalIndent(int numChars) {
240         if (fAdditionalIndentStack == null) {
241             fAdditionalIndentStack = new ArrayList JavaDoc();
242         }
243         fAdditionalIndentStack.add(new Integer JavaDoc(numChars));
244         fIndent += numChars;
245         setIndentPrefix();
246     }
247
248     /**
249      * Remove the last amount of additional indentation that was added.
250      */

251     public final void popAdditionalIndent() {
252         if ((fAdditionalIndentStack == null) || (fAdditionalIndentStack.size() == 0)) {
253             throw new XMLCError("additional identation stack underflow");
254         }
255         Integer JavaDoc numChars = (Integer JavaDoc)fAdditionalIndentStack.remove(fAdditionalIndentStack.size()-1);
256         fIndent -= numChars.intValue();
257         if (fIndent < 0) {
258             throw new XMLCError("identation level underflow");
259         }
260         setIndentPrefix();
261     }
262
263     /**
264      * Are we at the beginning of a line?
265      */

266     public boolean atBOLN() {
267         return fAtBOLN;
268     }
269
270     /**
271      * Write the current indentation and clear BOL flag.
272      */

273     private void printIndent() {
274         super.print(fIndentPrefix);
275         fAtBOLN = false;
276     }
277
278     /**
279      * Print a prefix for a line. If not at the beginning of a line, start a
280      * new one. Prefix will preceed indentation.
281      */

282     protected void printPrefix(String JavaDoc prefix) {
283         if (!fAtBOLN) {
284             println();
285         }
286         super.print(prefix);
287         printIndent();
288     }
289
290     /**
291      * Print a boolean value.
292      * @see java.io.Writer
293      */

294     public void print(boolean b) {
295         if (fAtBOLN) {
296             printIndent();
297         }
298         super.print(b);
299     }
300
301     /**
302      * Print a character.
303      * @see java.io.Writer
304      */

305     public void print(char c) {
306         if (fAtBOLN) {
307             printIndent();
308         }
309         super.print(c);
310     }
311
312     /**
313      * Print a long integer.
314      * @see java.io.Writer
315      */

316     public void print(long l) {
317         if (fAtBOLN) {
318             printIndent();
319         }
320         super.print(l);
321     }
322
323     /**
324      * Print a floating-point number.
325      * @see java.io.Writer
326      */

327     public void print(float f) {
328         if (fAtBOLN) {
329             printIndent();
330         }
331         super.print(f);
332     }
333
334     /**
335      * Print a double-precision floating-point number.
336      * @see java.io.Writer
337      */

338     public void print(double d) {
339         if (fAtBOLN) {
340             printIndent();
341         }
342         super.print(d);
343     }
344
345     /**
346      * Print an array of characters, indenting at the beginning of lines.
347      * The string is split at embedded newlines.
348      * @see java.io.Writer
349      */

350     public void print(char[] str) {
351         int idx = 0;
352         int strlen = str.length;
353         int nlIdx;
354
355         // Write string, breaking at
356
while (idx < strlen) {
357             if (fAtBOLN) {
358                 printIndent();
359             }
360             // Find next new line
361
for (nlIdx = idx; (nlIdx < strlen) && (str[nlIdx] != '\n'); nlIdx++) {
362             }
363             if (nlIdx < strlen) {
364                 write(str, idx, nlIdx-idx);
365                 println(); // Writes platform-dependent EOLN
366
} else {
367                 write(str, idx, strlen-idx);
368             }
369             idx = nlIdx+1;
370             fAtBOLN = true; // Last character was a newline.
371
}
372     }
373
374     /**
375      * Print a string, indenting at the beginning of lines.
376      * The string is split at embedded newlines.
377      * @see java.io.Writer
378      */

379     public void print(String JavaDoc str) {
380         int idx = 0;
381         int strlen = str.length();
382         int nlIdx;
383
384         // Write string upto last newline.
385
while ((idx < strlen) && ((nlIdx = str.indexOf('\n', idx)) >= 0)) {
386             if (fAtBOLN) {
387                 printIndent();
388             }
389             write(str, idx, nlIdx-idx);
390             println(); // Writes platform-dependent EOLN
391
idx = nlIdx+1;
392         }
393         
394         // Write characters following the last newline. If there
395
// were no newlines in the string, this writes the entire string.
396
if (idx < strlen) {
397             if (fAtBOLN) {
398                 printIndent();
399             }
400             write(str, idx, strlen-idx);
401         }
402     }
403
404     /**
405      * Print an object.
406      * @see java.io.Writer
407      */

408     public void print(Object JavaDoc obj) {
409         if (fAtBOLN) {
410             printIndent();
411         }
412         super.print(obj);
413     }
414
415     /**
416      * Terminate the current line by writing the line separator string.
417      * @see java.io.Writer
418      */

419     public void println() {
420     super.println();
421         fAtBOLN = true;
422     }
423
424     /**
425      * Write an array of strings, one line per string. Indenting at the
426      * beginning of the line. The string is split at embedded newlines.
427      * @see java.io.Writer
428      */

429     public void println(String JavaDoc[] strs) {
430         for (int i = 0; i < strs.length; i++) {
431             println(strs[i]);
432         }
433     }
434 }
435
Popular Tags