1
2
3
4
5
6
7
8
9
10
11 package com.legstar.cobol.gen;
12
13 import java.io.IOException;
14 import java.io.Writer;
15 import java.util.Arrays;
16
17 import org.antlr.stringtemplate.AutoIndentWriter;
18 import org.apache.commons.lang.StringUtils;
19
20
21
22
23
24
25
26
27 public class Copybook72ColWriter extends AutoIndentWriter {
28
29
30 public static final int STATEMENTS_LAST_COLUMN = 72;
31
32
33 public static final String LINE_CONTINUE_SENTENCE = " ";
34
35
36 public static final String LINE_CONTINUE_LITERAL = " - ";
37
38
39
40
41
42
43
44
45
46 private enum AlphanumLiteralStatus {
47 NOT_STARTED, STARTED, MAYBE_CLOSED
48 };
49
50
51 private AlphanumLiteralStatus alphanumLiteralStatus = AlphanumLiteralStatus.NOT_STARTED;
52
53
54
55
56
57 private char alphanumLiteralDelimiter;
58
59
60
61
62
63 private int indentPos;
64
65
66
67
68
69 private int tokenCounter = -1;
70
71
72
73
74
75 private StringBuilder keyword = new StringBuilder();
76
77 public Copybook72ColWriter(Writer out) {
78 super(out);
79 }
80
81
82
83
84
85
86
87
88
89 public int write(String str) throws IOException {
90 trackIndentation(str);
91 int n = 0;
92 for (int i = 0; i < str.length(); i++) {
93 char c = str.charAt(i);
94
95 if (c == '\r' || c == '\n') {
96 atStartOfLine = true;
97 charPosition = 0;
98 writeKeyword();
99 n += newline.length();
100 out.write(newline);
101
102 if ((c == '\r' && (i + 1) < str.length() && str.charAt(i + 1) == '\n')) {
103 i++;
104 }
105 continue;
106 }
107
108
109 if (atStartOfLine) {
110 atStartOfLine = false;
111 }
112
113 trackAlphanumLiteral(c);
114
115
116
117 if (charPosition == STATEMENTS_LAST_COLUMN) {
118 if (alphanumLiteralStatus == AlphanumLiteralStatus.NOT_STARTED) {
119 n += continueKeyword(str, indentPos);
120 } else {
121 n += continueAlphaLiteral();
122 }
123 }
124 n++;
125 writeKeywordOrAlphaLiteral(c);
126 charPosition++;
127
128 }
129 writeKeyword();
130 return n;
131 }
132
133
134
135
136
137
138
139
140
141 protected void writeKeywordOrAlphaLiteral(char c) throws IOException {
142 if (c == ' ') {
143 writeKeyword();
144 out.write(c);
145 } else {
146 if (alphanumLiteralStatus == AlphanumLiteralStatus.NOT_STARTED) {
147 keyword.append(c);
148 } else {
149 writeKeyword();
150 out.write(c);
151 }
152 }
153 }
154
155
156
157
158
159
160 protected void writeKeyword() throws IOException {
161 if (keyword.length() > 0) {
162 out.write(keyword.toString().toCharArray());
163 keyword = new StringBuilder();
164 }
165 }
166
167
168
169
170
171
172
173
174
175
176
177
178
179 protected void trackIndentation(String str) {
180 if (charPosition == 0) {
181 tokenCounter = 3;
182 }
183 if (tokenCounter == 0) {
184 indentPos = charPosition;
185 }
186 switch (tokenCounter) {
187 case 3:
188 if (StringUtils.isBlank(str)) {
189 tokenCounter = 2;
190 } else {
191 tokenCounter = -1;
192 }
193 break;
194 case 2:
195 if (str.matches("\\d\\d")) {
196 tokenCounter = 1;
197 } else {
198 tokenCounter = -1;
199 }
200 break;
201 case 1:
202 if (StringUtils.isBlank(str)) {
203 tokenCounter = 0;
204 } else {
205 tokenCounter = -1;
206 }
207 break;
208 default:
209 tokenCounter = -1;
210 }
211 }
212
213
214
215
216
217
218 protected void trackAlphanumLiteral(char c) {
219 if (c == '\'' || c == '\"') {
220 switch (alphanumLiteralStatus) {
221 case NOT_STARTED:
222 alphanumLiteralStatus = AlphanumLiteralStatus.STARTED;
223 alphanumLiteralDelimiter = c;
224 break;
225 case STARTED:
226 if (c == alphanumLiteralDelimiter) {
227 alphanumLiteralStatus = AlphanumLiteralStatus.MAYBE_CLOSED;
228 }
229 break;
230 case MAYBE_CLOSED:
231 if (c == alphanumLiteralDelimiter) {
232 alphanumLiteralStatus = AlphanumLiteralStatus.STARTED;
233 } else {
234 alphanumLiteralStatus = AlphanumLiteralStatus.NOT_STARTED;
235 }
236
237 }
238 } else {
239 if (alphanumLiteralStatus
240 .equals(AlphanumLiteralStatus.MAYBE_CLOSED)) {
241 alphanumLiteralStatus = AlphanumLiteralStatus.NOT_STARTED;
242 }
243 }
244 }
245
246
247
248
249
250
251
252
253
254
255
256
257 protected int continueAlphaLiteral() throws IOException {
258 String continueLiteral = newline + LINE_CONTINUE_LITERAL;
259 out.write(continueLiteral);
260 charPosition = LINE_CONTINUE_LITERAL.length();
261 int n = continueLiteral.length();
262 if (alphanumLiteralStatus.equals(AlphanumLiteralStatus.STARTED)) {
263 out.write(alphanumLiteralDelimiter);
264 charPosition++;
265 n++;
266 }
267 return n;
268 }
269
270
271
272
273
274
275
276
277
278
279 private int continueKeyword(String str, int indentPos) throws IOException {
280 return wrap(str, indentPos);
281 }
282
283
284
285
286
287
288
289
290
291
292 protected int wrap(String str, int indentPos) throws IOException {
293 int n = 0;
294 String wrap = getWrap(str, indentPos);
295
296
297 for (int i = 0; i < wrap.length(); i++) {
298 char c = wrap.charAt(i);
299 if (c == '\n') {
300 n++;
301 out.write(newline);
302 charPosition = 0;
303
304 } else {
305 n++;
306 out.write(c);
307 charPosition++;
308 }
309 }
310 return n;
311 }
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326 protected String getWrap(String str, int indentPos) {
327 int leadingSpaces = 0;
328 for (int i = 0; i < str.length(); i++) {
329 if (str.charAt(i) == ' ') {
330 leadingSpaces++;
331 } else {
332 break;
333 }
334 }
335 int indent = indentPos - leadingSpaces;
336 if (indent < 1 || indent + str.length() > STATEMENTS_LAST_COLUMN) {
337 return "\n" + LINE_CONTINUE_SENTENCE;
338 }
339 char[] chars = new char[indent];
340 Arrays.fill(chars, ' ');
341 return "\n" + new String(chars);
342 }
343
344 }