1/*
2 * Copyright (c) 1997, 2013, 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
26package com.sun.tools.internal.ws.processor.util;
27
28import com.sun.tools.internal.ws.processor.generator.GeneratorException;
29
30import java.io.BufferedWriter;
31import java.io.IOException;
32import java.io.Writer;
33import java.nio.charset.Charset;
34import java.nio.charset.CharsetEncoder;
35import java.text.MessageFormat;
36
37/**
38 *
39 * @author WS Development Team
40 */
41public class IndentingWriter extends BufferedWriter {
42
43    private boolean beginningOfLine = true;
44    private int currentIndent = 0;
45    private int indentStep = 4;
46
47    public IndentingWriter(Writer out) {
48        super(out);
49    }
50
51    public IndentingWriter(Writer out,int step) {
52        this(out);
53
54        if (indentStep < 0) {
55            throw new IllegalArgumentException("negative indent step");
56        }
57        indentStep = step;
58    }
59
60    public void write(int c) throws IOException {
61        checkWrite();
62        super.write(c);
63    }
64
65    public void write(char[] cbuf, int off, int len) throws IOException {
66        if (len > 0) {
67            checkWrite();
68        }
69        super.write(cbuf, off, len);
70    }
71
72    public void write(String s, int off, int len) throws IOException {
73        if (len > 0) {
74            checkWrite();
75        }
76        super.write(s, off, len);
77    }
78
79    public void newLine() throws IOException {
80        super.newLine();
81        beginningOfLine = true;
82    }
83
84    protected void checkWrite() throws IOException {
85        if (beginningOfLine) {
86            beginningOfLine = false;
87            int i = currentIndent;
88            while (i > 0) {
89                super.write(' ');
90                -- i;
91            }
92        }
93    }
94
95    protected void indentIn() {
96        currentIndent += indentStep;
97    }
98
99    protected void indentOut() {
100        currentIndent -= indentStep;
101        if (currentIndent < 0) {
102            currentIndent = 0;
103        }
104    }
105
106    public void pI() {
107        indentIn();
108    }
109
110    public void pO() {
111        indentOut();
112    }
113
114    public void pI(int levels) {
115        for (int i = 0; i < levels; ++i) {
116            indentIn();
117        }
118    }
119
120    public void pO(int levels) {
121        for (int i = 0; i < levels; ++i) {
122            indentOut();
123        }
124    }
125
126    public void p(String s) throws IOException {
127        /*
128        int tabCount = 0;
129        for (int i = 0; i < s.length(); ++i) {
130            if (s.charAt(i) == '\t') {
131                ++tabCount;
132                indentIn();
133            }
134        }
135
136        String printStr = s.substring(tabCount);
137         */
138        boolean canEncode = true;
139
140        //bug fix: 4839636
141        try{
142            if(!canEncode(s)) {
143                canEncode = false;
144            }
145        } catch (Throwable t) {
146
147            // there was some exception, what should we do?
148            // lets ignore it for now and proceed with the code generation!
149        }
150
151        if(!canEncode) {
152            throw new GeneratorException(
153                "generator.indentingwriter.charset.cantencode", s);
154        }
155        write(s);
156/*
157        while (tabCount-- > 0) {
158            indentOut();
159        }
160 */
161    }
162
163    /**
164     * Check if encode can handle the chars in this string.
165     *
166     */
167    protected boolean canEncode(String s) {
168        final CharsetEncoder encoder =
169            Charset.forName(System.getProperty("file.encoding")).newEncoder();
170        char[] chars = s.toCharArray();
171        for (int i=0; i<chars.length; i++) {
172            if(!encoder.canEncode(chars[i])) {
173                return false;
174            }
175        }
176        return true;
177    }
178
179    public void p(String s1, String s2) throws IOException {
180        p(s1);
181        p(s2);
182    }
183
184    public void p(String s1, String s2, String s3) throws IOException {
185        p(s1);
186        p(s2);
187        p(s3);
188    }
189
190    public void p(String s1, String s2, String s3, String s4) throws IOException {
191        p(s1);
192        p(s2);
193        p(s3);
194        p(s4);
195    }
196
197    public void p(String s1, String s2, String s3, String s4, String s5) throws IOException {
198        p(s1);
199        p(s2);
200        p(s3);
201        p(s4);
202        p(s5);
203    }
204
205    public void pln() throws IOException {
206        newLine();
207    }
208
209    public void pln(String s) throws IOException {
210        p(s);
211        pln();
212    }
213
214    public void pln(String s1, String s2) throws IOException {
215        p(s1, s2);
216        pln();
217    }
218
219    public void pln(String s1, String s2, String s3) throws IOException {
220        p(s1, s2, s3);
221        pln();
222    }
223
224    public void pln(String s1, String s2, String s3, String s4) throws IOException {
225        p(s1, s2, s3, s4);
226        pln();
227    }
228
229    public void pln(String s1, String s2, String s3, String s4, String s5) throws IOException {
230        p(s1, s2, s3, s4, s5);
231        pln();
232    }
233
234    public void plnI(String s) throws IOException {
235        p(s);
236        pln();
237        pI();
238    }
239
240    public void pO(String s) throws IOException {
241        pO();
242        p(s);
243    }
244
245    public void pOln(String s) throws IOException {
246        pO(s);
247        pln();
248    }
249
250    public void pOlnI(String s) throws IOException {
251        pO(s);
252        pln();
253        pI();
254    }
255
256    public void p(Object o) throws IOException {
257        write(o.toString());
258    }
259
260    public void pln(Object o) throws IOException {
261        p(o.toString());
262        pln();
263    }
264
265    public void plnI(Object o) throws IOException {
266        p(o.toString());
267        pln();
268        pI();
269    }
270
271    public void pO(Object o) throws IOException {
272        pO();
273        p(o.toString());
274    }
275
276    public void pOln(Object o) throws IOException {
277        pO(o.toString());
278        pln();
279    }
280
281    public void pOlnI(Object o) throws IOException {
282        pO(o.toString());
283        pln();
284        pI();
285    }
286
287    public void pM(String s) throws IOException {
288        int i = 0;
289        while (i < s.length()) {
290            int j = s.indexOf('\n', i);
291            if (j == -1) {
292                p(s.substring(i));
293                break;
294            } else {
295                pln(s.substring(i, j));
296                i = j + 1;
297            }
298        }
299    }
300
301    public void pMln(String s) throws IOException {
302        pM(s);
303        pln();
304    }
305
306    public void pMlnI(String s) throws IOException {
307        pM(s);
308        pln();
309        pI();
310    }
311
312    public void pMO(String s) throws IOException {
313        pO();
314        pM(s);
315    }
316
317    public void pMOln(String s) throws IOException {
318        pMO(s);
319        pln();
320    }
321
322    public void pF(String pattern, Object[] arguments) throws IOException {
323        pM(MessageFormat.format(pattern, arguments));
324    }
325
326    public void pFln(String pattern, Object[] arguments) throws IOException {
327        pF(pattern, arguments);
328        pln();
329    }
330}
331