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
40 import net.sourceforge.jenesis4java.*;
41 import net.sourceforge.jenesis4java.Access.AccessType;
42 import net.sourceforge.jenesis4java.exceptions.ImportConflictException;
43 import net.sourceforge.jenesis4java.impl.util.*;
44
45 import java.io.File;
46 import java.io.Serializable;
47 import java.util.ArrayList;
48 import java.util.Collections;
49 import java.util.Comparator;
50 import java.util.List;
51
52
53
54
55 abstract class MDeclaration extends MVM.MCodeable {
56
57
58
59
60 static class BlockDeclaration extends MMember {
61
62 List<Statement> vs = new ArrayList<>();
63
64 BlockDeclaration(MVM vm) {
65 super(vm);
66 }
67
68 @Override
69 public List<Statement> codeableList() {
70 return getStatements();
71 }
72
73 public List<Statement> getStatements() {
74 return ListTypeSelector.select(vs, Statement.class);
75 }
76
77 public Statement insertStatement(int index, Expression expression) {
78 ExpressionStatement expressionStatement = new MStatement.MExpressionStatement((MVM) vm(), expression);
79 vs.add(index, expressionStatement);
80 return expressionStatement;
81 }
82
83 public void insertStatement(int index, Statement statement) {
84 vs.add(index, statement);
85
86 }
87
88 @Override
89 public boolean isBlockWithAbruptCompletion() {
90 return BlockUtil.isBlockWithAbruptCompletion(getStatements());
91 }
92
93 public Break newBreak() {
94 Break x = new MStatement.MBreak(vm);
95 vs.add(x);
96 return x;
97 }
98
99 public Continue newContinue() {
100 Continue x = new MStatement.MContinue(vm);
101 vs.add(x);
102 return x;
103 }
104
105 public Let newDeclarationLet(Type type) {
106 Let x = new MStatement.MLet(vm, type);
107 int index = 0;
108 while (index < vs.size() && vs.get(index) instanceof Let) {
109 index++;
110 }
111 vs.add(index, x);
112 return x;
113 }
114
115 public DoWhile newDoWhile(Expression e) {
116 DoWhile x = new MStatement.MDoWhile(vm, e);
117 vs.add(x);
118 return x;
119 }
120
121 public Empty newEmpty() {
122 Empty x = new MStatement.MEmpty(vm);
123 vs.add(x);
124 return x;
125 }
126
127 public For newFor() {
128 For x = new MStatement.MFor(vm);
129 vs.add(x);
130 return x;
131 }
132
133 public If newIf(Expression e) {
134 If x = new MStatement.MIf(vm, e);
135 vs.add(x);
136 return x;
137 }
138
139 public Let newLet(Type type) {
140 Let x = new MStatement.MLet(vm, type);
141 vs.add(x);
142 return x;
143 }
144
145 public LocalBlock newLocalBlock() {
146 LocalBlock x = new MStatement.MLocalBlock(vm);
147 vs.add(x);
148 return x;
149 }
150
151 public LocalClass newLocalClass(String name) {
152 return newLocalClass(name, new MemberComparator());
153 }
154
155 public LocalClass newLocalClass(String name, Comparator comparator) {
156 LocalClass x = new MLocalClass(vm, name, comparator);
157 vs.add(x);
158 return x;
159 }
160
161 public Return newReturn() {
162 Return x = new MStatement.MReturn(vm);
163 vs.add(x);
164 return x;
165 }
166
167 public ExpressionStatement newStmt(Expression expr) {
168 ExpressionStatement x = new MStatement.MExpressionStatement(vm, expr);
169 vs.add(x);
170 return x;
171 }
172
173 public Switch newSwitch(Expression e) {
174 Switch x = new MStatement.MSwitch(vm, e);
175 vs.add(x);
176 return x;
177 }
178
179 public Synchronized newSynchronized(Expression e) {
180 Synchronized x = new MStatement.MSynchronized(vm, e);
181 vs.add(x);
182 return x;
183 }
184
185 public Throw newThrow(Expression e) {
186 Throw x = new MStatement.MThrow(vm, e);
187 vs.add(x);
188 return x;
189 }
190
191 public Try newTry() {
192 Try x = new MTry(vm);
193 vs.add(x);
194 return x;
195 }
196
197 public While newWhile(Expression e) {
198 While x = new MStatement.MWhile(vm, e);
199 vs.add(x);
200 return x;
201 }
202
203 public void removeStmt(Statement statement) {
204 vs.remove(statement);
205 }
206
207 @Override
208 public void visit(ReplacingVisitor visitor) {
209 super.visit(visitor);
210 VisitorUtils.visit(vs, this, visitor);
211 }
212 }
213
214
215
216
217 static class MAbstractMethod extends MMethod implements AbstractMethod {
218
219 MAbstractMethod(MVM vm, Type type, String name) {
220 super(vm, type, name);
221 isAbstract = true;
222 }
223
224 @Override
225 public CodeWriter toCode(CodeWriter out) {
226 super.toCode(out);
227
228 AccessType.toCode(access, out);
229
230 writeTypeParametersAndThrow(name, type, parameters, throwz, out);
231
232 out.write(';');
233
234 return out;
235 }
236 }
237
238
239
240
241 static class MClassDeclaration extends MTypeDeclaration implements ClassDeclaration {
242
243 String ex;
244
245 boolean isAbstract;
246
247 List<String> implementations = new ArrayList<>();
248
249 MClassDeclaration(MVM vm, MCompilationUnit unit) {
250 super(vm, unit);
251 }
252
253 @Override
254 public MClassDeclaration addImplements(String type) {
255 implementations.add(type);
256 return this;
257 }
258
259 @Override
260 public Import addImport(Class<?> clazz) {
261 return addImport(clazz.getName());
262 }
263
264 @Override
265 public Import addImport(String name) {
266 return getUnit().addImport(name);
267 }
268
269 @Override
270 public ClassType asClassType() {
271 return vm().newType(getUnit().getNamespace().getName() + "." + getName());
272 }
273
274 @Override
275 public List<Constructor> getConstructors() {
276 return ListTypeSelector.select(members, Constructor.class);
277 }
278
279 @Override
280 public String getExtends() {
281 return ex;
282 }
283
284 @Override
285 public List<ClassField> getFields() {
286 return ListTypeSelector.select(members, ClassField.class);
287 }
288
289 @Override
290 public List<String> getImplements() {
291 return ListTypeSelector.select(implementations);
292 }
293
294 public List<InitializationDeclaration> getInitializations() {
295 return ListTypeSelector.select(members, InitializationDeclaration.class);
296 }
297
298 @Override
299 public List<InnerClass> getInnerClasses() {
300 return ListTypeSelector.select(members, InnerClass.class);
301 }
302
303 @Override
304 public List<Member> getMembers() {
305 return ListTypeSelector.select(members, Member.class);
306 }
307
308 @Override
309 public List<ClassMethod> getMethods() {
310 return ListTypeSelector.select(members, ClassMethod.class);
311 }
312
313 @Override
314 public List<ClassMethod> getMethods(String methodName) {
315 List<ClassMethod> list = new ArrayList<>();
316 for (ClassMethod method : getMethods()) {
317 if (method.getName().equals(methodName)) {
318 list.add(method);
319 }
320 }
321 return list;
322 }
323
324 @Override
325 public List<StaticInitializer> getStaticInitializers() {
326 return ListTypeSelector.select(members, StaticInitializer.class);
327 }
328
329 @Override
330 public boolean isAbstract() {
331 return isAbstract;
332 }
333
334 @Override
335 public MClassDeclaration isAbstract(boolean value) {
336 isAbstract = value;
337 return this;
338 }
339
340 @Override
341 public boolean isMethodAlreadyDefined(Type type, String name) {
342 for (ClassMethod cm : getMethods()) {
343 if (cm.getName().equals(name) && cm.getType().equals(type)) {
344 return true;
345 }
346 }
347 return false;
348 }
349
350 @Override
351 public Constructor newConstructor() {
352 Constructor x = new MConstructor(vm, name);
353 members.add(x);
354 return x;
355 }
356
357 @Override
358 public ClassField newField(Class<?> type, String name) {
359 if (!type.getName().startsWith("java.lang.")) {
360 Class<?> typeToImport = type;
361 if (typeToImport.isArray()) {
362 typeToImport = typeToImport.getComponentType();
363 }
364 if (typeToImport != null) {
365 addImport(typeToImport);
366 }
367 }
368 return newField(vm.newType(type.getSimpleName()), name);
369 }
370
371 @Override
372 public ClassField newField(Type type, String name) {
373 ClassField x = new MClassField(vm, type, name);
374 members.add(x);
375 return x;
376 }
377
378 @Override
379 public InnerClass newInnerClass(String name) {
380 InnerClass x = new MInnerClass(vm, unit, this, name);
381 members.add(x);
382 return x;
383 }
384
385 @Override
386 public InnerInterface newInnerInterface(String name) {
387 MInnerInterface x = new MInnerInterface(vm, unit, this, name);
388 members.add(x);
389 return x;
390 }
391
392 @Override
393 public ClassMethod newMethod(String name) {
394 return newMethod(vm().newType(Type.VOID), name);
395 }
396
397 @Override
398 public ClassMethod newMethod(Type type, String name) {
399 ClassMethod x = new MClassMethod(vm, type, name);
400 members.add(x);
401 return x;
402 }
403
404 @Override
405 public StaticInitializer newStaticInitializer() {
406 StaticInitializer x = new MStaticInitializer(vm);
407 members.add(x);
408 return x;
409 }
410
411 @Override
412 public MClassDeclaration setExtends(String ex) {
413 this.ex = ex;
414 return this;
415 }
416
417 @Override
418 public CodeWriter toCode(CodeWriter out) {
419 super.toCode(out);
420
421 AccessType.toCode(access, out);
422
423 if (isAbstract) {
424 out.write("abstract ");
425 }
426 if (isStatic) {
427 out.write("static ");
428 }
429 if (isFinal) {
430 out.write("final ");
431 }
432
433
434 out.write("class ").write(name);
435
436
437 if (ex != null) {
438 out.space().write("extends ").write(ex);
439 }
440
441
442 if (!implementations.isEmpty()) {
443 out.space().write("implements ");
444 for (int i = 0; i < implementations.size(); i++) {
445 if (i > 0) {
446 out.write(", ");
447 }
448 out.write(implementations.get(i));
449 }
450 }
451 writeBlock(out, vm.getStyle("class"));
452 return out;
453 }
454
455 @Override
456 public boolean removeImplements(String interfaceName) {
457 return implementations.remove(interfaceName);
458 }
459 }
460
461
462
463
464 static class MClassField extends MField implements ClassField {
465
466
467 boolean isTransient;
468
469
470 boolean isVolatile;
471
472 public MClassField(MVM vm, Type type, String name) {
473 super(vm, type, name);
474 }
475
476 @Override
477 public boolean isTransient() {
478 return isTransient;
479 }
480
481 @Override
482 public MClassField isTransient(boolean isTransient) {
483 this.isTransient = isTransient;
484 return this;
485 }
486
487 @Override
488 public boolean isVolatile() {
489 return isVolatile;
490 }
491
492 @Override
493 public MClassField isVolatile(boolean isVolatile) {
494 this.isVolatile = isVolatile;
495 return this;
496 }
497
498 @Override
499 public CodeWriter toCode(CodeWriter out) {
500 super.toCode(out);
501 AccessType.toCode(access, out);
502
503 if (isTransient) {
504 out.write("transient ");
505 }
506 if (isVolatile) {
507 out.write("volatile ");
508 }
509 if (isStatic) {
510 out.write("static ");
511 }
512 if (isFinal) {
513 out.write("final ");
514 }
515
516
517 out.write(type).space().write(name);
518
519 if (expr != null) {
520 out.write(" = ").write(expr);
521 }
522
523 out.write(';');
524 if (comment != null && comment.getType() == Comment.TRAILING) {
525 out.write(comment);
526 }
527
528 return out;
529 }
530 }
531
532
533
534
535 static class MClassMethod extends MMethod implements ClassMethod {
536
537 boolean isNative;
538
539 boolean isSynchronized;
540
541 MClassMethod(MVM vm, Type type, String name) {
542 super(vm, type, name);
543 }
544
545 @Override
546 public boolean isNative() {
547 return isNative;
548 }
549
550 @Override
551 public MClassMethod isNative(boolean isNative) {
552 this.isNative = isNative;
553 return this;
554 }
555
556 @Override
557 public boolean isSynchronized() {
558 return isSynchronized;
559 }
560
561 @Override
562 public MClassMethod isSynchronized(boolean isSynchronized) {
563 this.isSynchronized = isSynchronized;
564 return this;
565 }
566
567 @Override
568 public CodeWriter toCode(CodeWriter out) {
569 super.toCode(out);
570 AccessType.toCode(access, out);
571
572 if (isAbstract) {
573 out.write("abstract ");
574 }
575 if (isNative) {
576 out.write("native ");
577 }
578 if (isSynchronized) {
579 out.write("synchronized ");
580 }
581 if (isStatic) {
582 out.write("static ");
583 }
584 if (isFinal) {
585 out.write("final ");
586 }
587
588 writeTypeParametersAndThrow(name, type, parameters, throwz, out);
589 if (isAbstract) {
590 out.write(";");
591 } else {
592 writeBlock(out, vm.getStyle("method"));
593 }
594
595 return out;
596 }
597
598 }
599
600
601
602
603 static class MCompilationUnit extends MDeclaration implements CompilationUnit {
604
605 boolean isEncoded;
606
607 List<TypeDeclaration> types = new ArrayList<>();
608
609 List<MImport> imports = new ArrayList<>();
610
611 final String codebase;
612
613 Namespace namespace;
614
615 MCompilationUnit(MVM vm, String codebase) {
616 super(vm);
617 this.codebase = codebase;
618 }
619
620 @Override
621 public Import addImport(Class<?> clazz) {
622 if (clazz == null) {
623 throw new IllegalArgumentException("Null is no legal import.");
624 }
625
626 return addImport(clazz.getName());
627 }
628
629 @Override
630 public Import addImport(String name) {
631 if (name == null) {
632 throw new IllegalArgumentException("Null is no legal import.");
633 } else if (name.trim().isEmpty()) {
634 throw new IllegalArgumentException("Empty import not supported.");
635 }
636
637 for (MImport im : imports) {
638 if (im.isClassnamePartOfImport(name)) {
639 return im;
640 }
641 if (im.isClassNameAlreadyUsed(name)) {
642 throw new ImportConflictException(im.getName(), name);
643 }
644 }
645 MImport x = new MImport(vm, name);
646 imports.add(x);
647 return x;
648 }
649
650 @Override
651 public MCompilationUnit encode() {
652
653 if (isEncoded) {
654 return this;
655 }
656 vm.getEncoder().encode(this);
657 isEncoded = true;
658 return this;
659 }
660
661 @Override
662 public String getCodebase() {
663 return codebase;
664 }
665
666 public String getFileName() {
667
668
669
670 StringBuilder file;
671
672
673 if (codebase != null && codebase.length() > 0) {
674 file = new StringBuilder(codebase);
675
676 if (!codebase.endsWith(Character.toString(File.separatorChar))) {
677
678 file.append(File.separatorChar);
679 }
680 } else {
681 file = new StringBuilder();
682 }
683
684
685 if (namespace != null) {
686
687 String pkg = namespace.getName();
688 if (pkg != null) {
689
690 file.append(pkg.replace('.', java.io.File.separatorChar));
691 }
692 }
693
694
695 String topLevelTypeName = getTopLevelType().getName();
696 int indexOfGeneric = topLevelTypeName.indexOf('<');
697 if (indexOfGeneric > 0) {
698 topLevelTypeName = topLevelTypeName.substring(0, indexOfGeneric).trim();
699 }
700 file.append(java.io.File.separatorChar).append(topLevelTypeName).append(".java");
701
702
703 return file.toString();
704 }
705
706 @Override
707 public List<Import> getImports() {
708 return ListTypeSelector.generalize(imports, Import.class);
709 }
710
711 @Override
712 public Namespace getNamespace() {
713 if (namespace == null) {
714 namespace = new MNamespace(vm, null);
715 }
716 return namespace;
717 }
718
719 @Override
720 public PackageClass getPackageClass(String name) {
721 if (name == null) {
722 return null;
723 }
724 for (PackageClass pc : ListTypeSelector.select(getTypes(), PackageClass.class)) {
725 if (pc.getName().equals(name)) {
726 return pc;
727 }
728 }
729 return null;
730 }
731
732 @Override
733 public TypeDeclaration getTopLevelType() {
734 return types.isEmpty() ? null : types.get(0);
735 }
736
737 @Override
738 public List<TypeDeclaration> getTypes() {
739 return ListTypeSelector.select(types, TypeDeclaration.class);
740 }
741
742 @Override
743 public PackageClass newClass(String name) {
744 PackageClass x = new MPackageClass(vm, this);
745 x.setName(name);
746 types.add(x);
747 return x;
748 }
749
750 @Override
751 public Interface newInterface(String name) {
752 Interface x = new MInterface(vm, this);
753 x.setName(name);
754 types.add(x);
755 return x;
756 }
757
758 @Override
759 public PackageClass newPublicClass(String name) {
760 return newClass(name)
761 .setAccess(AccessType.PUBLIC)
762 .cast(PackageClass.class);
763 }
764
765 @Override
766 public Interface newPublicInterface(String name) {
767 return newInterface(name)
768 .setAccess(AccessType.PUBLIC)
769 .cast(Interface.class);
770 }
771
772 @Override
773 public Namespace setNamespace(String name) {
774 namespace = new MNamespace(vm, name);
775 return namespace;
776 }
777
778 @Override
779 public CodeWriter toCode(CodeWriter out) {
780 out.setCompilationUnit(this);
781 if (comment != null) {
782 out.write(comment).newLine();
783 }
784
785 if (namespace != null) {
786 out.write(namespace).newLine();
787 }
788
789 if (!getImports().isEmpty()) {
790 out.write(getImports());
791 }
792
793 out.write(getTypes());
794
795 return out;
796 }
797
798 @Override
799 public void visit(ReplacingVisitor visitor) {
800 super.visit(visitor);
801 namespace = VisitorUtils.visit(namespace, this, visitor);
802 VisitorUtils.visit(imports, this, visitor);
803 VisitorUtils.visit(types, this, visitor);
804 }
805
806 }
807
808
809
810
811 static class MConstant extends MField implements Constant {
812
813 public MConstant(MVM vm, Type type, String name) {
814 super(vm, type, name);
815 isStatic = true;
816 isFinal = true;
817 }
818
819 @Override
820 public CodeWriter toCode(CodeWriter out) {
821 super.toCode(out);
822
823
824 out.write("static final ").write(type).space().write(name);
825
826 if (expr != null) {
827 out.write(" = ").write(expr);
828 }
829
830 out.write(';');
831 return out;
832 }
833 }
834
835
836
837
838 static class MConstructor extends MMethod implements Constructor {
839
840 private ConstructorForwarding forwarding;
841
842 MConstructor(MVM vm, String name) {
843 super(vm, null, name);
844 }
845
846 @Override
847 public ConstructorForwarding forwardCall(ForwardingTarget target) {
848 if (target == null) {
849 forwarding = null;
850 } else {
851 forwarding = new MStatement.MConstructorForwarding(vm, target);
852 }
853 return forwarding;
854 }
855
856 @Override
857 public MConstructor addThrows(String name) {
858 super.addThrows(name);
859 return this;
860 }
861
862 @Override
863 public CodeWriter toCode(CodeWriter out) {
864 super.toCode(out);
865 AccessType.toCode(access, out);
866
867 writeTypeParametersAndThrow(name, null, parameters, throwz, out);
868
869 writeBlock(out, vm.getStyle("constructor"));
870
871 return out;
872 }
873
874 @Override
875 public List<Statement> codeableList() {
876 if (forwarding != null) {
877 List<Statement> statements = new ArrayList<>();
878 statements.add(forwarding);
879 statements.addAll(super.codeableList());
880 return statements;
881 } else {
882 return super.codeableList();
883 }
884 }
885
886 @Override
887 public void visit(ReplacingVisitor visitor) {
888 super.visit(visitor);
889 forwarding = VisitorUtils.visit(forwarding, this, visitor);
890 }
891 }
892
893
894
895
896 abstract static class MField extends MMember implements Field {
897
898
899 Type type;
900
901
902 Expression expr;
903
904 public MField(MVM vm, Type type, String name) {
905 super(vm);
906 this.type = type;
907 this.name = name;
908 }
909
910 @Override
911 public Expression getExpression() {
912 return expr;
913 }
914
915 @Override
916 public Type getType() {
917 return type;
918 }
919
920 @Override
921 public MField setExpression(Expression expr) {
922 this.expr = expr;
923 return this;
924 }
925
926 @Override
927 public MField setType(Type type) {
928 this.type = type;
929 return this;
930 }
931
932 @Override
933 public CodeWriter toCode(CodeWriter out) {
934
935
936
937 out.ensureNewLine().newLine();
938
939 if (comment != null && comment.getType() != Comment.TRAILING) {
940 out.write(comment);
941 }
942
943 if (!annotations.isEmpty()) {
944 for (Annotation annotation : getAnnotations()) {
945 out.write(annotation);
946 out.newLine();
947 }
948 }
949 out.ensureNewLine();
950
951 return out;
952 }
953
954 @Override
955 public void visit(ReplacingVisitor visitor) {
956 super.visit(visitor);
957 type = VisitorUtils.visit(type, this, visitor);
958 expr = VisitorUtils.visit(expr, this, visitor);
959 }
960
961
962 @Override
963 List<Codeable> codeableList() {
964 return null;
965 }
966 }
967
968
969
970
971 static class MFormalParameter extends MDeclaration implements FormalParameter {
972
973 Type type;
974
975 String name;
976
977 boolean isFinal;
978
979 MFormalParameter(MVM vm, Type type, String name) {
980 super(vm);
981 this.type = type;
982 this.name = name;
983 }
984
985 @Override
986 public String getName() {
987 return name;
988 }
989
990 @Override
991 public Type getType() {
992 return type;
993 }
994
995 @Override
996 public boolean isFinal() {
997 return isFinal;
998 }
999
1000 @Override
1001 public MFormalParameter isFinal(boolean value) {
1002 isFinal = value;
1003 return this;
1004 }
1005
1006 @Override
1007 public MFormalParameter setName(String name) {
1008 this.name = name;
1009 return this;
1010 }
1011
1012 @Override
1013 public MFormalParameter setType(Type type) {
1014 this.type = type;
1015 return this;
1016 }
1017
1018 @Override
1019 public CodeWriter toCode(CodeWriter out) {
1020 out.queue(comment);
1021 if (isFinal) {
1022 out.write("final ");
1023 }
1024 out.write(type).space().write(name);
1025 return out;
1026 }
1027
1028 @Override
1029 public void visit(ReplacingVisitor visitor) {
1030 super.visit(visitor);
1031 type = VisitorUtils.visit(type, this, visitor);
1032 }
1033 }
1034
1035
1036
1037
1038 static class MImport extends MDeclaration implements Import {
1039
1040 String name;
1041
1042 MImport(MVM vm, String name) {
1043 super(vm);
1044 this.name = name;
1045 }
1046
1047 private static String baseClassName(String fullclassname) {
1048 int indexOfDot = fullclassname.lastIndexOf('.');
1049 return (indexOfDot < 0) ? fullclassname : fullclassname.substring(indexOfDot);
1050 }
1051
1052 @Override
1053 public String getName() {
1054 return name;
1055 }
1056
1057 public boolean isClassnamePartOfImport(String fullclassname) {
1058 if (isSingle()) {
1059 return getName().equals(fullclassname);
1060 } else {
1061 String packagename = getName().substring(0, getName().lastIndexOf('.'));
1062 return packagename.equals(fullclassname.substring(0, fullclassname.lastIndexOf('.')));
1063 }
1064 }
1065
1066 public boolean isClassNameAlreadyUsed(String fullclassname) {
1067 return isSingle() && baseClassName(getName()).equals(baseClassName(fullclassname));
1068 }
1069
1070 @Override
1071 public boolean isSingle() {
1072 return !name.endsWith("*");
1073 }
1074
1075 @Override
1076 public MImport setName(String name) {
1077 this.name = name;
1078 return this;
1079 }
1080
1081 @Override
1082 public CodeWriter toCode(CodeWriter out) {
1083 out.ensureNewLine();
1084 super.toCode(out);
1085 out.write("import ").write(name).write(';').newLine();
1086 return out;
1087 }
1088 }
1089
1090
1091
1092
1093 static class MInnerClass extends MClassDeclaration implements InnerClass {
1094
1095 final MClassDeclaration parent;
1096
1097 MInnerClass(MVM vm, MCompilationUnit unit, MClassDeclaration parent, String name) {
1098 super(vm, unit);
1099 this.parent = parent;
1100 this.name = name;
1101 this.setComparator(parent.getComparator());
1102 }
1103
1104 @Override
1105 public ClassDeclaration getParentClass() {
1106 return parent;
1107 }
1108
1109 @Override
1110 public void visit(ReplacingVisitor visitor) {
1111 super.visit(visitor);
1112
1113 }
1114 }
1115
1116
1117
1118
1119 static class MInnerInterface extends MInterface implements InnerInterface {
1120
1121 final MClassDeclaration parent;
1122
1123 MInnerInterface(MVM vm, MCompilationUnit unit, MClassDeclaration parent, String name) {
1124 super(vm, unit);
1125 this.parent = parent;
1126 this.name = name;
1127 this.setComparator(parent.getComparator());
1128 }
1129
1130 @Override
1131 public ClassDeclaration getParentClass() {
1132 return parent;
1133 }
1134
1135 @Override
1136 public void visit(ReplacingVisitor visitor) {
1137 super.visit(visitor);
1138
1139 }
1140 }
1141
1142
1143
1144
1145 static class MInterface extends MTypeDeclaration implements Interface {
1146
1147 List<String> extendz = new ArrayList<>();
1148
1149 MInterface(MVM vm, MCompilationUnit unit) {
1150 super(vm, unit);
1151 }
1152
1153 @Override
1154 public Interface addExtends(String ex) {
1155 extendz.add(ex);
1156 return this;
1157 }
1158
1159 @Override
1160 public ClassType asClassType() {
1161 return vm().newType(getUnit().getNamespace().getName() + "." + getName());
1162 }
1163
1164 @Override
1165 public List<String> getExtends() {
1166 return ListTypeSelector.select(extendz);
1167 }
1168
1169 @Override
1170 public Constant newConstant(String name, int val) {
1171 Constant x = new MConstant(vm, vm.INT, name);
1172 x.setExpression(new MLiteral.MIntLiteral(vm, val));
1173 members.add(x);
1174 return x;
1175 }
1176
1177 @Override
1178 public Constant newConstant(Type type, String name) {
1179 Constant x = new MConstant(vm, type, name);
1180 members.add(x);
1181 return x;
1182 }
1183
1184 @Override
1185 public AbstractMethod newMethod(String name) {
1186 return newMethod(vm().newType(Type.VOID), name);
1187 }
1188
1189 @Override
1190 public AbstractMethod newMethod(Type type, String name) {
1191 AbstractMethod x = new MAbstractMethod(vm, type, name);
1192 members.add(x);
1193 return x;
1194 }
1195
1196 @Override
1197 public CodeWriter toCode(CodeWriter out) {
1198 super.toCode(out);
1199
1200 AccessType.toCode(access, out);
1201
1202 if (isFinal) {
1203 out.write("final ");
1204 }
1205 out.write("interface ").write(name);
1206
1207 if (!extendz.isEmpty()) {
1208 out.newLine().write("extends ");
1209
1210 for (int i = 0; i < extendz.size(); i++) {
1211 if (i > 0) {
1212 out.write(", ");
1213 }
1214 out.write(extendz.get(i));
1215 }
1216 }
1217
1218 writeBlock(out, vm.getStyle("interface"));
1219 return out;
1220 }
1221
1222 @Override
1223 public boolean removeExtends(String className) {
1224 return extendz.remove(className);
1225 }
1226 }
1227
1228
1229
1230
1231 static class MLocalClass extends MClassDeclaration implements LocalClass {
1232
1233 String label;
1234
1235 MLocalClass(MVM vm, String name, Comparator comparator) {
1236 super(vm, null);
1237
1238
1239
1240 this.name = name;
1241 setComparator(comparator);
1242 }
1243
1244 @Override
1245 public Comment comment(String text) {
1246 Comment sl = new MComment.MSingleLineComment(vm, text);
1247 comment = sl;
1248 return sl;
1249 }
1250
1251 @Override
1252 public String getLabel() {
1253 return label;
1254 }
1255
1256 @Override
1257 public boolean isAbruptCompletionStatement() {
1258 return false;
1259 }
1260
1261 @Override
1262 public MLocalClass setLabel(String label) {
1263 this.label = label;
1264 return this;
1265 }
1266
1267 @Override
1268 public CodeWriter toCode(CodeWriter out) {
1269 super.toCode(out);
1270
1271 out.write(";");
1272
1273 return out;
1274 }
1275
1276 @Override
1277 public void visit(ReplacingVisitor visitor) {
1278 super.visit(visitor);
1279
1280 }
1281 }
1282
1283
1284
1285
1286 abstract static class MMember extends MDeclaration implements Member {
1287
1288 String name;
1289
1290 AccessType access = Access.PACKAGE;
1291
1292 boolean isFinal;
1293
1294 boolean isStatic;
1295
1296 List<Annotation> annotations = new ArrayList<>();
1297
1298 MMember(MVM vm) {
1299 super(vm);
1300 }
1301
1302 @Override
1303 public MMember addAnnotation(Annotation annotation) {
1304 annotations.add(annotation);
1305 return this;
1306 }
1307
1308 @Override
1309 public Annotation addAnnotation(String text) {
1310 Annotation x = new MAnnotation(vm, text);
1311 annotations.add(x);
1312 return x;
1313 }
1314
1315 @Override
1316 public AccessType getAccess() {
1317 return access;
1318 }
1319
1320 @Override
1321 public List<Annotation> getAnnotations() {
1322 return ListTypeSelector.select(annotations, Annotation.class);
1323 }
1324
1325 @Override
1326 public String getName() {
1327 return name;
1328 }
1329
1330 @Override
1331 public boolean isFinal() {
1332 return isFinal;
1333 }
1334
1335 @Override
1336 public MMember isFinal(boolean value) {
1337 isFinal = value;
1338 return this;
1339 }
1340
1341 @Override
1342 public boolean isStatic() {
1343 return isStatic;
1344 }
1345
1346 @Override
1347 public MMember isStatic(boolean value) {
1348 isStatic = value;
1349 return this;
1350 }
1351
1352 @Override
1353 public MMember setAccess(AccessType access) {
1354 this.access = access;
1355 return this;
1356 }
1357
1358 @Override
1359 public MMember setName(String name) {
1360 this.name = name;
1361 return this;
1362 }
1363
1364 @Override
1365 public CodeWriter toCode(CodeWriter out) {
1366 out.ensureNewLine().newLine();
1367
1368 if (comment != null && comment.getType() != Comment.TRAILING) {
1369 out.write(comment);
1370 }
1371
1372 if (!annotations.isEmpty()) {
1373 out.ensureNewLine();
1374 for (Annotation annotation : getAnnotations()) {
1375 out.write(annotation);
1376 out.newLine();
1377 }
1378 }
1379 out.ensureNewLine();
1380
1381 return out;
1382 }
1383
1384 @Override
1385 public void visit(ReplacingVisitor visitor) {
1386 super.visit(visitor);
1387 VisitorUtils.visit(annotations, this, visitor);
1388 }
1389
1390 abstract List<? extends Codeable> codeableList();
1391
1392 void writeBlock(CodeWriter out, BlockStyle style) {
1393 style.toCode(out, codeableList(), comment);
1394 }
1395 }
1396
1397
1398
1399
1400 abstract static class MMethod extends BlockDeclaration implements Method {
1401
1402 boolean isAbstract;
1403
1404 List<FormalParameter> parameters = new ArrayList<>();
1405
1406 List<String> throwz = new ArrayList<>();
1407
1408 Type type;
1409
1410 MMethod(MVM vm, Type type, String name) {
1411 super(vm);
1412 this.type = type;
1413 this.name = name;
1414 }
1415
1416 @Override
1417 public FormalParameter addParameter(Class type, String name) {
1418 return addParameter(vm.newType(type), name);
1419 }
1420
1421 @Override
1422 public FormalParameter addParameter(Type type, String name) {
1423 FormalParameter x = new MFormalParameter(vm, type, name);
1424 parameters.add(x);
1425 return x;
1426 }
1427
1428 @Override
1429 public MMethod addThrows(String name) {
1430 throwz.add(name);
1431 return this;
1432 }
1433
1434 @Override
1435 public List<FormalParameter> getParameters() {
1436 return ListTypeSelector.select(parameters, FormalParameter.class);
1437 }
1438
1439 @Override
1440 public List<String> getThrows() {
1441 return ListTypeSelector.select(throwz, String.class);
1442 }
1443
1444 @Override
1445 public Type getType() {
1446 return type;
1447 }
1448
1449 @Override
1450 public boolean isAbstract() {
1451 return isAbstract;
1452 }
1453
1454 @Override
1455 public MMethod isAbstract(boolean isAbstract) {
1456 this.isAbstract = isAbstract;
1457 return this;
1458 }
1459
1460 @Override
1461 public MMethod setType(Type type) {
1462 this.type = type;
1463 return this;
1464 }
1465
1466 @Override
1467 public void visit(ReplacingVisitor visitor) {
1468 super.visit(visitor);
1469 VisitorUtils.visit(parameters, this, visitor);
1470 type = VisitorUtils.visit(type, this, visitor);
1471 }
1472 }
1473
1474
1475
1476
1477 static class MNamespace extends MDeclaration implements Namespace {
1478
1479 String name;
1480
1481 MNamespace(MVM vm, String name) {
1482 super(vm);
1483 this.name = name;
1484 }
1485
1486 @Override
1487 public String getName() {
1488 return name;
1489 }
1490
1491 @Override
1492 public MNamespace setName(String name) {
1493 this.name = name;
1494 return this;
1495 }
1496
1497 @Override
1498 public CodeWriter toCode(CodeWriter out) {
1499 out.ensureNewLine();
1500 super.toCode(out);
1501 out.write("package ").write(name).write(';').newLine();
1502 return out;
1503 }
1504
1505 }
1506
1507
1508
1509
1510 static class MPackageClass extends MClassDeclaration implements PackageClass {
1511
1512 MPackageClass(MVM vm, MCompilationUnit unit) {
1513 super(vm, unit);
1514 }
1515
1516 @Override
1517 public MPackageClass addSerializable() {
1518 getUnit().addImport(Serializable.class.getName());
1519
1520 addImplements(Serializable.class.getSimpleName());
1521
1522 ClassField serialVersionUID = newField(vm.newType(Type.LONG), "serialVersionUID");
1523 serialVersionUID.setExpression(vm.newLong(1L))
1524 .isFinal(true)
1525 .isStatic(true)
1526 .setAccess(Access.PRIVATE);
1527 return this;
1528
1529 }
1530 }
1531
1532
1533
1534
1535 static class MStaticInitializer extends BlockDeclaration implements StaticInitializer {
1536
1537 MStaticInitializer(MVM vm) {
1538 super(vm);
1539 }
1540
1541 @Override
1542 public CodeWriter toCode(CodeWriter out) {
1543 super.toCode(out);
1544
1545
1546 out.write("static");
1547 writeBlock(out, vm.getStyle("static-initializer"));
1548 return out;
1549 }
1550 }
1551
1552
1553
1554
1555 abstract static class MTypeDeclaration extends MMember implements TypeDeclaration {
1556
1557 final MCompilationUnit unit;
1558
1559 List<Declaration> members;
1560
1561 private Comparator<Member> comparator;
1562
1563 MTypeDeclaration(MVM vm, MCompilationUnit unit) {
1564 super(vm);
1565 this.unit = unit;
1566 members = new ArrayList<>();
1567 this.comparator = new MemberComparator();
1568 }
1569
1570 @Override
1571 public List<Member> getMembers() {
1572 return ListTypeSelector.select(members, Member.class);
1573 }
1574
1575 @Override
1576 public CompilationUnit getUnit() {
1577 return unit;
1578 }
1579
1580 @Override
1581 public void visit(ReplacingVisitor visitor) {
1582 super.visit(visitor);
1583 VisitorUtils.visit(members, this, visitor);
1584 }
1585
1586 public Comparator<Member> getComparator() {
1587 return this.comparator;
1588 }
1589
1590 public void setComparator(final Comparator comparator) {
1591 this.comparator = comparator;
1592 this.visit(new ReplacingVisitor() {
1593 @Override
1594 public Codeable visitReplace(Codeable current, Codeable parent) {
1595 if (current!= null) {
1596 if (current instanceof TypeDeclaration) {
1597 ((TypeDeclaration) current).setComparator(comparator);
1598 }
1599 current.visit(this);
1600 }
1601 return current;
1602 }
1603 });
1604 }
1605
1606 @Override
1607 List<Member> codeableList() {
1608 return sort(getMembers());
1609 }
1610
1611
1612
1613
1614
1615 String getClassfile() {
1616
1617 StringBuilder className = new StringBuilder();
1618
1619
1620
1621 if (unit.namespace != null) {
1622
1623 String pkg = unit.namespace.getName();
1624
1625 if (pkg != null) {
1626
1627 className.append(pkg).append('.');
1628 }
1629 }
1630
1631
1632 className.append(getName());
1633
1634
1635 return className.toString();
1636 }
1637
1638 List<Member> sort(List<Member> list) {
1639 List<Member> result = new ArrayList<>(list);
1640 Collections.sort(result, getComparator());
1641 return result;
1642 }
1643
1644 @Override
1645 public boolean removeMember(Member member) {
1646 return members.remove(member);
1647 }
1648 }
1649
1650 MDeclaration(MVM vm) {
1651 super(vm);
1652 }
1653
1654 private static void writeTypeParametersAndThrow(String name, Type type, List<FormalParameter> parameters, List<String> throwz, CodeWriter out) {
1655
1656 if (type != null) {
1657 out.write(type).space();
1658 }
1659 out.write(name).write('(');
1660
1661 for (int i = 0; i < parameters.size(); i++) {
1662 if (i > 0) {
1663 out.write(", ");
1664 }
1665 out.write(parameters.get(i));
1666 }
1667
1668 out.write(')');
1669
1670 if (!throwz.isEmpty()) {
1671 out.space().write("throws ");
1672 for (int i = 0; i < throwz.size(); i++) {
1673 if (i > 0) {
1674 out.write(", ");
1675 }
1676 out.write(throwz.get(i));
1677 }
1678 }
1679 }
1680
1681 public DocumentationComment javadoc(String text) {
1682 comment = new MComment.MDocumentationComment(vm, text);
1683 return (DocumentationComment) comment;
1684 }
1685 }