1 /*
2  * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.rmi.rmic.newrmic;
27 
28 import java.io.Writer;
29 import java.io.BufferedWriter;
30 import java.io.IOException;
31 
32 /**
33  * A BufferedWriter that supports automatic indentation of lines of
34  * text written to the underlying Writer.
35  *
36  * Methods are provided for compact/convenient indenting in and out,
37  * writing text, and writing lines of text in various combinations.
38  *
39  * WARNING: The contents of this source file are not part of any
40  * supported API.  Code that depends on them does so at its own risk:
41  * they are subject to change or removal without notice.
42  *
43  * @author Peter Jones
44  **/
45 public class IndentingWriter extends BufferedWriter {
46 
47     /** number of spaces to change indent when indenting in or out */
48     private final int indentStep;
49 
50     /** number of spaces to convert into tabs (use MAX_VALUE to disable) */
51     private final int tabSize;
52 
53     /** true if the next character written is the first on a line */
54     private boolean beginningOfLine = true;
55 
56     /** current number of spaces to prepend to lines */
57     private int currentIndent = 0;
58 
59     /**
60      * Creates a new IndentingWriter that writes indented text to the
61      * given Writer.  Use the default indent step of four spaces.
62      **/
IndentingWriter(Writer out)63     public IndentingWriter(Writer out) {
64         this(out, 4);
65     }
66 
67     /**
68      * Creates a new IndentingWriter that writes indented text to the
69      * given Writer and uses the supplied indent step.
70      **/
IndentingWriter(Writer out, int indentStep)71     public IndentingWriter(Writer out, int indentStep) {
72         this(out, indentStep, 8);
73     }
74 
75     /**
76      * Creates a new IndentingWriter that writes indented text to the
77      * given Writer and uses the supplied indent step and tab size.
78      **/
IndentingWriter(Writer out, int indentStep, int tabSize)79     public IndentingWriter(Writer out, int indentStep, int tabSize) {
80         super(out);
81         if (indentStep < 0) {
82             throw new IllegalArgumentException("negative indent step");
83         }
84         if (tabSize < 0) {
85             throw new IllegalArgumentException("negative tab size");
86         }
87         this.indentStep = indentStep;
88         this.tabSize = tabSize;
89     }
90 
91     /**
92      * Writes a single character.
93      **/
write(int c)94     public void write(int c) throws IOException {
95         checkWrite();
96         super.write(c);
97     }
98 
99     /**
100      * Writes a portion of an array of characters.
101      **/
write(char[] cbuf, int off, int len)102     public void write(char[] cbuf, int off, int len) throws IOException {
103         if (len > 0) {
104             checkWrite();
105         }
106         super.write(cbuf, off, len);
107     }
108 
109     /**
110      * Writes a portion of a String.
111      **/
write(String s, int off, int len)112     public void write(String s, int off, int len) throws IOException {
113         if (len > 0) {
114             checkWrite();
115         }
116         super.write(s, off, len);
117     }
118 
119     /**
120      * Writes a line separator.  The next character written will be
121      * preceded by an indent.
122      **/
newLine()123     public void newLine() throws IOException {
124         super.newLine();
125         beginningOfLine = true;
126     }
127 
128     /**
129      * Checks if an indent needs to be written before writing the next
130      * character.
131      *
132      * The indent generation is optimized (and made consistent with
133      * certain coding conventions) by condensing groups of eight
134      * spaces into tab characters.
135      **/
checkWrite()136     protected void checkWrite() throws IOException {
137         if (beginningOfLine) {
138             beginningOfLine = false;
139             int i = currentIndent;
140             while (i >= tabSize) {
141                 super.write('\t');
142                 i -= tabSize;
143             }
144             while (i > 0) {
145                 super.write(' ');
146                 i--;
147             }
148         }
149     }
150 
151     /**
152      * Increases the current indent by the indent step.
153      **/
indentIn()154     protected void indentIn() {
155         currentIndent += indentStep;
156     }
157 
158     /**
159      * Decreases the current indent by the indent step.
160      **/
indentOut()161     protected void indentOut() {
162         currentIndent -= indentStep;
163         if (currentIndent < 0)
164             currentIndent = 0;
165     }
166 
167     /**
168      * Indents in.
169      **/
pI()170     public void pI() {
171         indentIn();
172     }
173 
174     /**
175      * Indents out.
176      **/
pO()177     public void pO() {
178         indentOut();
179     }
180 
181     /**
182      * Writes string.
183      **/
p(String s)184     public void p(String s) throws IOException {
185         write(s);
186     }
187 
188     /**
189      * Ends current line.
190      **/
pln()191     public void pln() throws IOException {
192         newLine();
193     }
194 
195     /**
196      * Writes string; ends current line.
197      **/
pln(String s)198     public void pln(String s) throws IOException {
199         p(s);
200         pln();
201     }
202 
203     /**
204      * Writes string; ends current line; indents in.
205      **/
plnI(String s)206     public void plnI(String s) throws IOException {
207         p(s);
208         pln();
209         pI();
210     }
211 
212     /**
213      * Indents out; writes string.
214      **/
pO(String s)215     public void pO(String s) throws IOException {
216         pO();
217         p(s);
218     }
219 
220     /**
221      * Indents out; writes string; ends current line.
222      **/
pOln(String s)223     public void pOln(String s) throws IOException {
224         pO(s);
225         pln();
226     }
227 
228     /**
229      * Indents out; writes string; ends current line; indents in.
230      *
231      * This method is useful for generating lines of code that both
232      * end and begin nested blocks, like "} else {".
233      **/
pOlnI(String s)234     public void pOlnI(String s) throws IOException {
235         pO(s);
236         pln();
237         pI();
238     }
239 
240     /**
241      * Writes object.
242      **/
p(Object o)243     public void p(Object o) throws IOException {
244         write(o.toString());
245     }
246 
247     /**
248      * Writes object; ends current line.
249      **/
pln(Object o)250     public void pln(Object o) throws IOException {
251         p(o.toString());
252         pln();
253     }
254 
255     /**
256      * Writes object; ends current line; indents in.
257      **/
plnI(Object o)258     public void plnI(Object o) throws IOException {
259         p(o.toString());
260         pln();
261         pI();
262     }
263 
264     /**
265      * Indents out; writes object.
266      **/
pO(Object o)267     public void pO(Object o) throws IOException {
268         pO();
269         p(o.toString());
270     }
271 
272     /**
273      * Indents out; writes object; ends current line.
274      **/
pOln(Object o)275     public void pOln(Object o) throws IOException {
276         pO(o.toString());
277         pln();
278     }
279 
280     /**
281      * Indents out; writes object; ends current line; indents in.
282      *
283      * This method is useful for generating lines of code that both
284      * end and begin nested blocks, like "} else {".
285      **/
pOlnI(Object o)286     public void pOlnI(Object o) throws IOException {
287         pO(o.toString());
288         pln();
289         pI();
290     }
291 }
292