1
package mso.generator;
2
3
import java.io.FileWriter;
4
import java.io.IOException;
5
import java.io.PrintWriter;
6
import java.util.regex.Matcher;
7
import java.util.regex.Pattern;
8
9
import mso.generator.utils.Choice;
10
import mso.generator.utils.Limitation;
11
import mso.generator.utils.MSO;
12
import mso.generator.utils.Member;
13
import mso.generator.utils.Stream;
14
import mso.generator.utils.Struct;
15
import mso.generator.utils.TypeRegistry;
16
17
public class JavaParserGenerator {
18
	void generate(MSO mso, String dir, String packagename, String classname)
19
			throws IOException {
20
		FileWriter fout = new FileWriter(dir + "/"
21
				+ packagename.replace('.', '/') + "/" + classname + ".java");
22
		PrintWriter out = new PrintWriter(fout);
23
		out.println("package " + packagename + ";");
24
		out.println("import java.io.IOException;");
25
		out.println("public class " + classname + " {");
26
		out
27
				.println("    Object parse(String key, LEInputStream in) throws IOException {");
28
		boolean first = true;
29
		for (Stream s : mso.streams) {
30
			out.print("        ");
31
			if (first) {
32
				first = false;
33
			} else {
34
				out.print("} else ");
35
			}
36
			out.println("if (\"" + s.key + "\".equals(key)) {"); // TODO: fix
37
			// for
38
			// \001 and \005
39
			// prefix
40
			out.println("            return parse" + s.type + "(in);");
41
		}
42
		out.println("        } else {");
43
		out.println("            return parseTODOS(in);");
44
		out.println("        }");
45
		out.println("    }");
46
47
		out
48
				.println("    void serialize(String key, Object o, LEOutputStream out) throws IOException {");
49
		first = true;
50
		for (Stream s : mso.streams) {
51
			out.print("        ");
52
			if (first) {
53
				first = false;
54
			} else {
55
				out.print("} else ");
56
			}
57
			out.println("if (\"" + s.key + "\".equals(key)) {"); // TODO: fix
58
			// for
59
			// \001 and \005
60
			// prefix
61
			out.println("            write((" + s.type + ")o, out);");
62
		}
63
		out.println("        } else {");
64
		out.println("            write((TODOS)o, out);");
65
		out.println("        }");
66
		out.println("    }");
67
68
		for (Struct s : mso.structs) {
69
			printStructureParser(out, s);
70
			printStructureWriter(out, s);
71
		}
72
73
		out.println("}");
74
75
		for (Struct s : mso.structs) {
76
			printStructureClass(out, s);
77
		}
78
79
		out.close();
80
		fout.close();
81
	}
82
83
	void printStructureParser(PrintWriter out, Struct s) {
84
		out.println("    " + s.name + " parse" + s.name
85
				+ "(LEInputStream in) throws IOException  {");
86
		out.println("        " + s.name + " _s = new " + s.name + "();");
87
		if (s.containsKnownLengthArrayMember) {
88
			out.println("        int _c;");
89
		}
90
		boolean variableArray = false;
91
		for (Member m : s.members) {
92
			if (m.isArray && m.count == null && m.size == null) {
93
				variableArray = s.containsUnknownLengthArrayMember;
94
			}
95
		}
96
		if (s.containsOptionalMember || variableArray
97
				|| s.containsChoice) {
98
			out.println("        Object _m;");
99
		}
100
		if (variableArray) {
101
			out.println("        boolean _atend;");
102
		}
103
		for (Member m : s.members) {
104
			printStructureMemberParser(out, m);
105
		}
106
		if (s.name.contains("RecordHeader")) {
107
			out.println("System.out.println(in.getPosition()+\" \"+_s);");
108
		}
109
		out.println("        return _s;");
110
		out.println("    }");
111
	}
112
113
	void printStructureWriter(PrintWriter out, Struct s) {
114
		out.println("    void write(" + s.name
115
				+ " _s, LEOutputStream out) throws IOException  {");
116
		for (Member m : s.members) {
117
			printStructureMemberWriter(out, m);
118
		}
119
		out.println("    }");
120
	}
121
122
	void printStructureMemberWriter(PrintWriter out, Member m) {
123
		String s = "        ";
124
		if (m.condition != null) {
125
			out.println("        if (" + getExpression("_s", m.condition)
126
					+ ") {");
127
			s = s + "    ";
128
		}
129
		if (m.isChoice) {
130
			boolean first = true;
131
			Choice c = (Choice) m.type();
132
			for (String t : c.getChoiceNames()) {
133
				out.print(s);
134
				if (!first) {
135
					out.print("} else ");
136
				}
137
				first = false;
138
				out.println("if (_s." + m.name + " instanceof " + t + ") {");
139
				out
140
						.println(s + "    write((" + t + ")_s." + m.name
141
								+ ", out);");
142
			}
143
			out.println(s + "}");
144
		} else if (m.isArray) {
145
			String t = getTypeName(m);
146
			out.println(s + "for (" + t + " _i: _s." + m.name + ") {");
147
			if (m.isStruct) {
148
				out.println(s + "    write(_i, out);");
149
			} else {
150
				out.println(s + "    out.write" + m.type().name + "(_i);");
151
			}
152
			out.println(s + "}");
153
		} else if (m.isStruct) {
154
			out.print(s);
155
			if (m.isOptional) {
156
				out.print("if (_s." + m.name + " != null) ");
157
			}
158
			out.println("write(_s." + m.name + ", out);");
159
		} else {
160
			out.println(s + "out.write" + m.type().name + "(_s." + m.name
161
					+ ");");
162
		}
163
		if (m.condition != null) {
164
			out.println("        }");
165
		}
166
	}
167
168
	String getTypeName(Member m) {
169
		final TypeRegistry.Type t = m.type();
170
		final TypeRegistry r = m.registry;
171
		if (t instanceof Struct) {
172
			return m.type().name;
173
		} else if (t instanceof Choice) {
174
			return "Object";
175
		} else if (t == r.bit) {
176
			return "boolean";
177
		} else if (t == r.uint2 || t == r.uint3 || t == r.uint4 || t == r.uint5
178
				|| t == r.uint6 || t == r.uint7 || t == r.uint8) {
179
			return "byte";
180
		} else if (t == r.uint9 || t == r.uint12 || t == r.uint13
181
				|| t == r.uint14 || t == r.uint15
182
				|| t == r.int16) {
183
			return "short";
184
		} else if (t == r.uint16 || t == r.uint20 || t == r.uint30
185
				|| t == r.uint32 || t == r.int32) {
186
			return "int";
187
		}
188
		return t.name;
189
	}
190
191
	String getMemberDeclaration(Member m) {
192
		if (m.isArray) {
193
			if (m.count == null) {
194
				return "final java.util.List<" + m.type().name + "> " + m.name
195
						+ " = new java.util.ArrayList<" + m.type().name + ">()";
196
			} else {
197
				return getTypeName(m) + "[] " + m.name;
198
			}
199
		} else {
200
			return getTypeName(m) + " " + m.name;
201
		}
202
	}
203
204
	void printStructureClass(PrintWriter out, Struct s) {
205
		out.println("class " + s.name + " {");
206
		for (Member m : s.members) {
207
			String d = getMemberDeclaration(m);
208
			out.println("    " + d + ";");
209
		}
210
211
		// function toString
212
		out.println("    public String toString() {");
213
		out.println("        String _s = \"" + s.name + ":\";");
214
		for (Member m : s.members) {
215
			out.print("        _s = _s + \"" + m.name
216
					+ ": \" + String.valueOf(" + m.name + ") + \"");
217
			if (m.isInteger && !m.isArray) {
218
				out.print("(\" + Integer.toHexString(" + m.name
219
						+ ").toUpperCase() + \")");
220
			}
221
			out.println(", \";");
222
		}
223
		out.println("        return _s;");
224
		out.println("    }");
225
		out.println("}");
226
227
	}
228
229
	String prependStructureToExpression(String expression, String structureName) {
230
		if (expression.length() > 0) {
231
			Pattern p = Pattern.compile("([^.\\w])([.a-zA-Z])");
232
			Matcher m = p.matcher(expression);
233
			expression = m.replaceAll("$1" + structureName + ".$2");
234
			p = Pattern.compile("^([a-zA-Z])");
235
			m = p.matcher(expression);
236
			expression = m.replaceAll(structureName + ".$1");
237
		}
238
		return expression;
239
	}
240
241
	void printStructureMemberParser(PrintWriter out, Member m) {
242
		String s = "        ";
243
		String condition = null;
244
		if (m.condition != null) {
245
			condition = prependStructureToExpression(m.condition, "_s");
246
			s = s + "    ";
247
			out.println("        if (" + condition + ") {");
248
		}
249
		String count = null;
250
		if (m.count != null) {
251
			count = prependStructureToExpression(m.count, "_s");
252
		}
253
		String parse;
254
		if (m.isStruct) {
255
			parse = "parse" + m.type().name + "(in);";
256
		} else {
257
			parse = "in.read" + m.type().name + "();";
258
		}
259
260
		if (m.isChoice) {
261
			printChoiceParser(out, s, m);
262
			return;
263
		}
264
		if (m.isArray && m.count == null) {
265
			if (m.size != null) {
266
				printFixedSizeArrayParser(out, s, m);
267
			} else {
268
				// array for which no size is given: parse items until one fails
269
				printVariableArrayParser(out, s, m);
270
			}
271
			return;
272
		}
273
		if (m.isOptional) {
274
			printOptionalMemberParser(out, s, m);
275
			return;
276
		}
277
		if (count != null) {
278
			out.println(s + "_c = " + count + ";");
279
		}
280
		out.print(s + "_s." + m.name + " = ");
281
		if (count != null) {
282
			if (m.type() == m.registry.uint8) {
283
				out.println("in.readBytes(_c);");
284
			} else {
285
				out.println("new " + getTypeName(m) + "[_c];");
286
				out.println(s + "for (int _j=0; _j<_c; ++_j) {");
287
				out.println(s + "    _s." + m.name + "[_j] = " + parse);
288
				printLimitationCheck(out, "            ", "_s." + m.name
289
						+ "[_j]", m);
290
				out.println(s + "}");
291
			}
292
		} else {
293
			out.println(parse);
294
			printLimitationCheck(out, "        ", "_s." + m.name, m);
295
		}
296
		if (condition != null) {
297
			out.println("        }");
298
		}
299
	}
300
301
	void printChoiceParser(PrintWriter out, String s, Member m) {
302
		String closing = "";
303
		String exception = "_x";
304
		out.println(s + "_m = in.setMark();");
305
		Choice c = (Choice) m.type();
306
		String choices[] = c.getChoiceNames();
307
		int length = (m.isOptional) ? choices.length : choices.length - 1;
308
		for (int i = 0; i < length; ++i) {
309
			out.println(s + "try {");
310
			out.println(s + "    _s." + m.name + " = parse" + choices[i]
311
					+ "(in);");
312
			out.println(s + "} catch (IOException " + exception + ") {");
313
			out.println(s + "    if (!(" + exception
314
					+ " instanceof IncorrectValueException) && !(" + exception
315
					+ " instanceof java.io.EOFException)) throw " + exception
316
					+ ";");
317
			// out
318
			// .println(s
319
			// + "    if (in.distanceFromMark(_m) > 16) throw new IOException("
320
			// + exception + ");//onlyfordebug");
321
			out.println(s + "    in.rewind(_m);");
322
			exception = exception + "x";
323
			closing = closing + "}";
324
		}
325
		if (!m.isOptional) {
326
			out.println(s + "    _s." + m.name + " = parse"
327
					+ choices[choices.length - 1] + "(in);");
328
		}
329
		out.println(s + closing + " finally {");
330
		out.println(s + "    in.releaseMark(_m);");
331
		out.println(s + "}");
332
	}
333
334
	void printFixedSizeArrayParser(PrintWriter out, String s, Member m) {
335
		out.println(s + "int _startPos = in.getPosition();");
336
		out.println(s + "while (in.getPosition() - _startPos < "
337
				+ getExpression("_s", m.size) + ") {");
338
		out.println(s + "    " + m.type().name + " _t = parse" + m.type().name
339
				+ "(in);");
340
		out.println(s + "    _s." + m.name + ".add(_t);");
341
		out.println(s + "}");
342
	}
343
344
	void printVariableArrayParser(PrintWriter out, String s, Member m) {
345
		out.println(s + "_atend = false;");
346
		out.println(s + "while (!_atend) {");
347
		// out
348
		// .println(s
349
		// +
350
		// "    System.out.println(\"round \"+(_i++) + \" \" + in.getPosition());");
351
		out.println(s + "    _m = in.setMark();");
352
		out.println(s + "    try {");
353
		out.println(s + "        " + m.type().name + " _t = parse"
354
				+ m.type().name + "(in);");
355
		out.println(s + "        _s." + m.name + ".add(_t);");
356
		out.println(s + "    } catch(IncorrectValueException _e) {");
357
		// out
358
		// .println(s
359
		// +
360
		// "    if (in.distanceFromMark(_m) > 16) throw new IOException(_e);//onlyfordebug");
361
		out.println(s + "        _atend = true;");
362
		out.println(s + "        in.rewind(_m);");
363
		out.println(s + "    } catch(java.io.EOFException _e) {");
364
		out.println(s + "        _atend = true;");
365
		out.println(s + "        in.rewind(_m);");
366
		out.println(s + "    } finally {");
367
		out.println(s + "        in.releaseMark(_m);");
368
		out.println(s + "   }");
369
		out.println(s + "}");
370
	}
371
372
	void printOptionalMemberParser(PrintWriter out, String s, Member m) {
373
		out.println(s + "_m = in.setMark();");
374
		out.println(s + "try {");
375
		out.println(s + "    _s." + m.name + " = parse" + m.type().name
376
				+ "(in);");
377
		out.println(s + "} catch(IncorrectValueException _e) {");
378
		out
379
				.println(s
380
						+ "    if (in.distanceFromMark(_m) > 16) throw new IOException(_e);//onlyfordebug");
381
		out.println(s + "    in.rewind(_m);");
382
		out.println(s + "} catch(java.io.EOFException _e) {");
383
		out.println(s + "    in.rewind(_m);");
384
		out.println(s + "} finally {");
385
		out.println(s + "    in.releaseMark(_m);");
386
		out.println(s + "}");
387
	}
388
389
	void printLimitationCheck(PrintWriter out, String s, String name, Member m) {
390
		for (Limitation l : m.limitations) {
391
			String mname = l.name;
392
			if (!"".equals(mname)) {
393
				mname = name + "." + mname;
394
			} else {
395
				mname = name;
396
			}
397
			String condition;
398
			if (l.expression == null) {
399
				condition = getCondition(mname, l);
400
			} else {
401
				condition = getExpression(mname, l.expression);
402
			}
403
404
			out.println(s + "if (!(" + condition + ")) {");
405
			String exceptionType = "IncorrectValueException";
406
			// if (!condition.contains(".recType")
407
			// && !condition.contains(".recVer")
408
			// && !condition.contains(".recInstance")) {
409
			// // special value for debugging: we only have recoverable
410
			// // exceptions in record headers, remove this in final code
411
			// exceptionType = "IOException";
412
			// }
413
			out.println(s + "    throw new " + exceptionType
414
					+ "(in.getPosition() + \"" + condition
415
					+ " for value \" + String.valueOf(" + name + ") );");
416
			out.println(s + "}");
417
		}
418
	}
419
420
	String getExpression(String structure, String expression) {
421
		if (Pattern.matches(".*[A-Za-z].*", expression)) {
422
			return prependStructureToExpression(expression, structure);
423
		}
424
		return structure + expression;
425
	}
426
427
	String getCondition(String name, Limitation l) {
428
		String value = l.value;
429
		String cmp = " == ";
430
		String cmb = " || ";
431
		if (value.startsWith("!")) {
432
			value = value.substring(1);
433
			cmp = " != ";
434
			cmb = " && ";
435
		}
436
		if (value.contains("|")) {
437
			String values[] = value.split("\\|");
438
			String c = name + cmp + values[0];
439
			for (int i = 1; i < values.length; ++i) {
440
				c = c + cmb + name + cmp + values[i];
441
			}
442
			return c;
443
		}
444
		return name + cmp + value;
445
	}
446
}