1 package net.sourceforge.jenesis4java.impl;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 import java.io.BufferedInputStream;
40 import java.io.FileInputStream;
41 import java.io.IOException;
42 import java.io.PrintWriter;
43 import java.io.StringWriter;
44 import java.util.*;
45
46 import net.sourceforge.jenesis4java.*;
47 import net.sourceforge.jenesis4java.impl.util.BlockStyle;
48 import net.sourceforge.jenesis4java.impl.util.MemberComparator;
49 import net.sourceforge.jenesis4java.impl.util.VisitorUtils;
50
51
52
53
54 public class MVM extends net.sourceforge.jenesis4java.VirtualMachine {
55
56
57
58
59 abstract static class MCodeable implements Codeable {
60
61 Comment comment;
62
63 MVM vm;
64
65 MCodeable(MVM vm) {
66 this.vm = vm;
67 }
68
69 @Override
70 public <T> T cast(Class<T> clazz) {
71 return clazz.cast(this);
72 }
73
74 @Override
75 public Comment getComment() {
76 return comment;
77 }
78
79 @Override
80 public boolean isBlockWithAbruptCompletion() {
81 return false;
82 }
83
84 private Set<Style> activeStyles = EnumSet.noneOf(Style.class);
85
86 @Override
87 public MCodeable setComment(int type, String text) {
88 switch (type) {
89 case Comment.SINGLE_LINE:
90 comment = new MComment.MSingleLineComment(vm, text);
91 break;
92 case Comment.MULTI_LINE:
93 comment = new MComment.MMultipleLineComment(vm, text);
94 break;
95 case Comment.BLOCK_WITHOUT_INTERMEDIARY_STARS:
96 comment = new MComment.MMultipleLineComment(vm, text, true);
97 break;
98 case Comment.DOCUMENTATION:
99 comment = new MComment.MDocumentationComment(vm, text);
100 break;
101 case Comment.TRAILING:
102 comment = new MComment.MSingleLineComment(vm, text, true);
103 break;
104 default:
105 String message = type + " is no valid comment type. "
106 + "Use a constant in Comment.";
107 throw new IllegalArgumentException(message);
108 }
109 return this;
110 }
111
112 @Override
113 public CodeWriter toCode(CodeWriter out) {
114 if (comment != null) {
115 out.write(comment);
116 }
117 return out;
118 }
119
120 @Override
121 public String toString() {
122 StringWriter sout = new StringWriter();
123 PrintWriter pout = new PrintWriter(sout);
124 CodeWriter cout = new MCodeWriter(pout);
125 toCode(cout);
126 return sout.toString();
127 }
128
129 @Override
130 public void visit(ReplacingVisitor visitor) {
131 comment = VisitorUtils.visit(comment, this, visitor);
132 }
133
134 @Override
135 public VirtualMachine vm() {
136 return vm;
137 }
138
139 @Override
140 public Codeable applyStyle(Style style) {
141 activeStyles.add(style);
142 return this;
143 }
144
145 @Override
146 public boolean isActive(Style style) {
147 return activeStyles.contains(style);
148 }
149 }
150
151 PrimitiveType VOID;
152
153 PrimitiveType NULL;
154
155 PrimitiveType BOOLEAN;
156
157 PrimitiveType BYTE;
158
159 PrimitiveType SHORT;
160
161 PrimitiveType INT;
162
163 PrimitiveType CHAR;
164
165 PrimitiveType LONG;
166
167 PrimitiveType FLOAT;
168
169 PrimitiveType DOUBLE;
170
171 ClassType STRING;
172
173 ClassType BIGDECIMAL_TYPE;
174
175 ClassType BOOLEAN_TYPE;
176
177 ClassType CALENDAR_TYPE;
178
179 ClassType INTEGER_TYPE;
180
181 ClassType LONG_TYPE;
182
183 ClassType STRING_TYPE;
184
185 Null _NULL;
186
187 True TRUE;
188
189 False FALSE;
190
191 MStyle.MStyleMap styles;
192
193
194
195 final ArrayList<CompilationUnit> units = new ArrayList<>();
196
197 CompilationUnitEncoder encoder;
198
199 public MVM(java.util.Properties styleprops) {
200 initTypes();
201 styles = new MStyle.MStyleMap(styleprops);
202 try {
203 encoder = (CompilationUnitEncoder) Class.forName(styleprops.getProperty("encoder", BasicCompilationUnitEncoder.class.getName())).newInstance();
204 } catch (Exception e) {
205 throw new RuntimeException("encoder class not found!", e);
206 }
207 }
208
209 public MVM(String styleprops) throws IOException {
210 this(readProperties(styleprops));
211 }
212
213 private static Properties readProperties(String properties) throws IOException {
214 Properties p;
215 try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(properties))) {
216
217 p = new Properties();
218 p.load(in);
219 }
220 return p;
221 }
222
223 @Override
224 public synchronized VirtualMachine clear() {
225 units.clear();
226 return this;
227 }
228
229 @Override
230 public MVM encode() {
231 for (CompilationUnit c : cloneUnits()) {
232 c.encode();
233 }
234 return this;
235 }
236
237 @SuppressWarnings("unchecked")
238 private synchronized List<CompilationUnit> cloneUnits() {
239 return (List<CompilationUnit>) units.clone();
240 }
241
242 @Override
243 public CompilationUnitEncoder getEncoder() {
244 return encoder;
245 }
246
247 @Override
248 public FieldAccess newAccess(Class<?> qualifierClass, Object object) {
249 return newAccess(qualifierClass.getSimpleName(), object.toString());
250 }
251
252 @Override
253 public FieldAccess newAccess(Expression qual, String name) {
254 return new MExpression.MFieldAccess(this, qual, name);
255 }
256
257 @Override
258 public FieldAccess newAccess(String name) {
259 return new MExpression.MFieldAccess(this, (String) null, name);
260 }
261
262 @Override
263 public FieldAccess newAccess(String qual, String name) {
264 return new MExpression.MFieldAccess(this, qual, name);
265 }
266
267 @Override
268 public Annotation newAnnotation(Class<?> annotationClass) {
269 return newAnnotation(annotationClass.getSimpleName());
270 }
271
272 @Override
273 public Annotation newAnnotation(String text) {
274 return new MAnnotation(this, text);
275 }
276
277 @Override
278 public AnnotationAttribute newAnnotationAttribute(String key, Expression value, Expression... additionalValues) {
279 MAnnotation.MAnnotationAttribute attribute = new MAnnotation.MAnnotationAttribute(this);
280 attribute.setName(key);
281 attribute.addValue(value);
282 for (Expression val : additionalValues) {
283 attribute.addValue(val);
284 }
285 return attribute;
286 }
287
288 @Override
289 public NewAnonymousClass newAnon(Type type, Comparator comparator) {
290 return new MExpression.MNewAnonymousClass(this, type, comparator);
291 }
292
293 @Override
294 public NewAnonymousClass newAnon(Type type) {
295 return newAnon(type, new MemberComparator());
296 }
297
298 @Override
299 public NewAnonymousClass newAnonymousClass(String className, Comparator comparator, String... genericTypes) {
300 return newAnon(newType(className + createTypeParameters(genericTypes)), comparator);
301 }
302
303 @Override
304 public NewAnonymousClass newAnonymousClass(String className, String... genericTypes) {
305 return newAnon(newType(className + createTypeParameters(genericTypes)));
306 }
307
308 @Override
309 public ArrayType newArray(int type, int name) {
310 return new MType.MArrayType(this, newType(type), name);
311 }
312
313 @Override
314 public ArrayType newArray(String type, int dims) {
315 return new MType.MArrayType(this, newType(type), dims);
316 }
317
318 @Override
319 public NewArray newArray(Type type) {
320 return new MExpression.MNewArray(this, type);
321 }
322
323 public ArrayType newArray(Type type, int dims) {
324 return new MType.MArrayType(this, type, dims);
325 }
326
327 @Override
328 public ArrayAccess newArrayAccess(Expression qual, String name) {
329 return new MExpression.MArrayAccess(this, qual, name);
330 }
331
332 @Override
333 public ArrayAccess newArrayAccess(String name) {
334 return new MExpression.MArrayAccess(this, (String) null, name);
335 }
336
337 @Override
338 public ArrayAccess newArrayAccess(String qual, String name) {
339 return new MExpression.MArrayAccess(this, qual, name);
340 }
341
342 @Override
343 public ArrayInitializer newArrayInit(Expression[] expressions) {
344 return new MExpression.MArrayInitializer(this, expressions);
345 }
346
347 @Override
348 public ArrayInitializer newArrayInit(Object o) {
349 return new MExpression.MArrayInitializer(this, o);
350 }
351
352 @Override
353 public Assign newAssign(int type, Variable l, Expression r) {
354 return new MExpression.MAssign(this, type, l, r);
355 }
356
357 @Override
358 public Assign newAssign(Variable l, Expression r) {
359 return new MExpression.MAssign(this, Assign.S, l, r);
360 }
361
362 @Override
363 public Binary newBinary(int type, Expression l, Expression r) {
364 return new MExpression.MBinary(this, type, l, r);
365 }
366
367 @Override
368 public Blank newBlank() {
369 return new MExpression.MBlank(this);
370 }
371
372 @Override
373 public BooleanLiteral newBoolean(boolean value) {
374 return value ? newTrue() : newFalse();
375 }
376
377 @Override
378 public Cast newBrackets(Expression expression) {
379 return newCast(null, expression);
380 }
381
382 @Override
383 public ByteLiteral newByte(byte val) {
384 return new MLiteral.MByteLiteral(this, val);
385 }
386
387 @Override
388 public CalendarClassType newCalendarType(String pattern) {
389 return new MType.MCalendarClassType(this, pattern);
390 }
391
392 @Override
393 public Cast newCast(Type type, Expression val) {
394 return new MExpression.MCast(this, type, val);
395 }
396
397 @Override
398 public CharLiteral newChar(char val) {
399 return new MLiteral.MCharLiteral(this, val);
400 }
401
402 @Override
403 public NewClass newClass(Type type) {
404 return new MExpression.MNewClass(this, type);
405 }
406
407 @Override
408 public ClassLiteral newClassLiteral(ClassType val) {
409 return new MLiteral.MClassLiteral(this, val);
410 }
411
412 @Override
413 public ClassLiteral newClassLiteral(String val) {
414 return new MLiteral.MClassLiteral(this, newType(val));
415 }
416
417 @Override
418 public synchronized CompilationUnit newCompilationUnit(String path) {
419 CompilationUnit x = new MDeclaration.MCompilationUnit(this, path);
420 units.add(x);
421 return x;
422 }
423
424 @Override
425 public CompilationUnit newCompilationUnit(String sourceDirectory, String packageName) {
426 CompilationUnit unit = newCompilationUnit(sourceDirectory);
427 unit.setNamespace(packageName);
428 return unit;
429 }
430
431 @Override
432 public DoubleLiteral newDouble(double val) {
433 return new MLiteral.MDoubleLiteral(this, val);
434 }
435
436 @Override
437 public False newFalse() {
438 return FALSE;
439 }
440
441 @Override
442 public FloatLiteral newFloat(float val) {
443 return new MLiteral.MFloatLiteral(this, val);
444 }
445
446 @Override
447 public Freeform newFree(String code) {
448 return new MExpression.MFreeform(this, code);
449 }
450
451 @Override
452 public IntLiteral newInt(int val) {
453 return new MLiteral.MIntLiteral(this, val);
454 }
455
456 @Override
457 public Invoke newInvoke(Class<?> qualifyingClass, String name) {
458 return newInvoke(qualifyingClass.getSimpleName(), name);
459 }
460
461 @Override
462 public Invoke newInvoke(Expression qual, String name) {
463 return new MExpression.MInvoke(this, qual, name);
464 }
465
466 @Override
467 public Invoke newInvoke(String name) {
468 return newInvoke((String) null, name);
469 }
470
471 @Override
472 public Invoke newInvoke(String qual, String name) {
473 return new MExpression.MInvoke(this, qual, name);
474 }
475
476 @Override
477 public LongLiteral newLong(long val) {
478 return new MLiteral.MLongLiteral(this, val);
479 }
480
481 @Override
482 public Null newNull() {
483 return _NULL;
484 }
485
486 @Override
487 public OctalLiteral newOctal(char val) {
488 return new MLiteral.MOctalLiteral(this, val);
489 }
490
491 @Override
492 public ScientificLiteral newScientific(int precision, int scale, int exponent) {
493 return new MLiteral.MScientificLiteral(this, precision, scale, exponent);
494 }
495
496 @Override
497 public ShortLiteral newShort(short val) {
498 return new MLiteral.MShortLiteral(this, val);
499 }
500
501 @Override
502 public ClassType newSimpleType(Class<?> type) {
503 return newType(type.getSimpleName());
504 }
505
506 @Override
507 public StringLiteral newString(String val) {
508 return new MLiteral.MStringLiteral(this, val);
509 }
510
511 @Override
512 public Ternary newTernary(int type, Expression one, Expression two, Expression three) {
513 return new MExpression.MTernary(this, type, one, two, three);
514 }
515
516 @Override
517 public True newTrue() {
518 return TRUE;
519 }
520
521 @Override
522 public ClassType newType(Class<?> clazz) {
523 return newType(clazz.getName());
524 }
525
526 @Override
527 public PrimitiveType newType(int type) {
528 switch (type) {
529 case Type.VOID:
530 return VOID;
531 case Type.NULL:
532 return NULL;
533 case Type.BOOLEAN:
534 return BOOLEAN;
535 case Type.BYTE:
536 return BYTE;
537 case Type.SHORT:
538 return SHORT;
539 case Type.INT:
540 return INT;
541 case Type.LONG:
542 return LONG;
543 case Type.FLOAT:
544 return FLOAT;
545 case Type.DOUBLE:
546 return DOUBLE;
547 case Type.CHAR:
548 return CHAR;
549
550 case Type.ARRAY:
551 throw new IllegalArgumentException("Cannot create array Type with this method.");
552 case Type.CLASS:
553 throw new IllegalArgumentException("Cannot create class Type with this method.");
554 default:
555 String message = "Illegal type constant " + type + ". Use constants defined in Type.";
556 throw new IllegalArgumentException(message);
557 }
558 }
559
560 @Override
561 public ClassType newType(String name) {
562 return new MType.MClassType(this, name);
563 }
564
565 @Override
566 public Unary newUnary(int type, Expression val) {
567 return new MExpression.MUnary(this, type, val);
568 }
569
570 @Override
571 public UnicodeLiteral newUnicode(char val) {
572 return new MLiteral.MUnicodeLiteral(this, val);
573 }
574
575 @Override
576 public Variable newVar(String name) {
577 return new MExpression.MVariable(this, name);
578 }
579
580 @Override
581 public Variable newVar(Type type) {
582 return new MExpression.MTypeVariable(this, type);
583 }
584
585 @Override
586 public Type type_boolean() {
587 return BOOLEAN;
588 }
589
590 @Override
591 public Type type_byte() {
592 return BYTE;
593 }
594
595 @Override
596 public Type type_char() {
597 return CHAR;
598 }
599
600 @Override
601 public Type type_double() {
602 return DOUBLE;
603 }
604
605 @Override
606 public Type type_float() {
607 return FLOAT;
608 }
609
610 @Override
611 public Type type_int() {
612 return INT;
613 }
614
615 @Override
616 public Type type_long() {
617 return LONG;
618 }
619
620 @Override
621 public Type type_short() {
622 return SHORT;
623 }
624
625 @Override
626 public Type type_void() {
627 return VOID;
628 }
629
630 @Override
631 public ClassType typeBigDecimal() {
632 return BIGDECIMAL_TYPE;
633 }
634
635 @Override
636 public ClassType typeBoolean() {
637 return BOOLEAN_TYPE;
638 }
639
640 @Override
641 public ClassType typeCalendar() {
642 return CALENDAR_TYPE;
643 }
644
645 @Override
646 public ClassType typeInteger() {
647 return INTEGER_TYPE;
648 }
649
650 @Override
651 public ClassType typeLong() {
652 return LONG_TYPE;
653 }
654
655 @Override
656 public ClassType typeString() {
657 return STRING_TYPE;
658 }
659
660 @Override
661 public Super newSuper() {
662 return new MExpression.MSuper(this);
663 }
664
665 @Override
666 public This newThis() {
667 return new MExpression.MThis(this);
668 }
669
670 @Override
671 public This newThis(ClassType typeOfOuterClass) {
672 return new MExpression.MThis(this, typeOfOuterClass);
673 }
674
675 private String createTypeParameters(String[] genericTypes) {
676 if (genericTypes == null || genericTypes.length == 0) {
677 return "";
678 }
679 StringBuilder builder = new StringBuilder("<");
680 boolean first = true;
681 for (String type : genericTypes) {
682 if (!first) {
683 builder.append(", ");
684 } else {
685 first = false;
686 }
687 builder.append(type);
688 }
689 return builder.append(">").toString();
690 }
691
692 BlockStyle getStyle(String name) {
693 return styles.get(name);
694 }
695
696 private void initTypes() {
697 VOID = new MType.MPrimitiveType(this, Type.VOID, "void");
698 NULL = new MType.MPrimitiveType(this, Type.NULL, "null");
699 BOOLEAN = new MType.MPrimitiveType(this, Type.BOOLEAN, "boolean");
700 BYTE = new MType.MPrimitiveType(this, Type.BYTE, "byte");
701 SHORT = new MType.MPrimitiveType(this, Type.SHORT, "short");
702 INT = new MType.MPrimitiveType(this, Type.INT, "int");
703 CHAR = new MType.MPrimitiveType(this, Type.CHAR, "char");
704 LONG = new MType.MPrimitiveType(this, Type.LONG, "long");
705 FLOAT = new MType.MPrimitiveType(this, Type.FLOAT, "float");
706 DOUBLE = new MType.MPrimitiveType(this, Type.DOUBLE, "double");
707 STRING = new MType.MClassType(this, "String");
708 _NULL = new MLiteral.MNull(this);
709 TRUE = new MLiteral.MTrue(this);
710 FALSE = new MLiteral.MFalse(this);
711
712 BIGDECIMAL_TYPE = new MType.MClassType(this, java.math.BigDecimal.class.getName());
713 BOOLEAN_TYPE = new MType.MClassType(this, Boolean.class.getName());
714 CALENDAR_TYPE = new MType.MClassType(this, java.util.Calendar.class.getName());
715 INTEGER_TYPE = new MType.MClassType(this, Integer.class.getName());
716 LONG_TYPE = new MType.MClassType(this, Long.class.getName());
717 STRING_TYPE = new MType.MClassType(this, String.class.getName());
718 }
719 }