package io.trygvis.container.compiler.model; import javax.lang.model.type.TypeMirror; import java.io.PrintWriter; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import static java.lang.reflect.Modifier.*; import static org.springframework.util.StringUtils.collectionToDelimitedString; public class ClassG { public final TypeRef type; private final TypeRef extendsClass; private final Set imports = new TreeSet<>(); private final Set fields = new TreeSet<>(); private final List methods = new ArrayList<>(); private final List constructors = new ArrayList<>(); public ClassG(TypeRef type) { this(type, null); } public ClassG(TypeRef type, TypeRef extendsClass) { this.type = type; this.extendsClass = extendsClass; } public TypeRef addImport(final TypeMirror type) { return addImport(new TypeRef(type)); } public TypeRef addImport(Class c) { return addImport(new TypeRef(c)); } public TypeRef addImport(TypeRef klass) { String fqName = klass.fqName; String name = klass.name; for (TypeRef i : imports) { if (i.fqName.equals(fqName)) { return i; } // If we've already found an import with the same name, use the fq version if (i.name.equals(name)) { name = fqName; break; } } TypeRef ref = new TypeRef(name, fqName); imports.add(ref); return ref; } public FieldRef addField(TypeMirror klass, String name) { TypeRef type = addImport(klass); FieldRef ref = new FieldRef(PRIVATE | FINAL, type, name); fields.add(ref); return ref; } public FieldRef addField(int modifiers, Class klass, String name) { TypeRef type = addImport(klass); FieldRef ref = new FieldRef(modifiers, type, name); fields.add(ref); return ref; } public FieldRef addField(Class klass, String name) { return addField(PRIVATE | FINAL, klass, name); } public FieldRef addPublicFinalField(Class klass, String name) { return addField(PUBLIC | FINAL, klass, name); } public FieldRef addPublicStaticFinalField(Class klass, String name) { return addField(PUBLIC | STATIC | FINAL, klass, name); } public Constructor addConstructor(Parameters parameters, List body) { Constructor constructor = new Constructor(this, parameters, body); constructors.add(constructor); return constructor; } public MethodRef addMethod(List body, TypeRef returnType, String name, ParameterRef... parameters) { MethodRef ref = new MethodRef(PUBLIC, returnType, name, parameters, body); methods.add(ref); return ref; } public MethodRef addStaticMethod(List body, TypeRef returnType, String name, ParameterRef... parameters) { MethodRef ref = new MethodRef(PUBLIC | STATIC, returnType, name, parameters, body); methods.add(ref); return ref; } public void write(PrintWriter writer) { if (!type.inUnnamedPackage()) { writer.println("package " + type.packageName() + ";"); writer.println(); } for (TypeRef i : imports) { if (i.isPrimitive() || i.inUnnamedPackage()) { continue; } writer.println("import " + i.fqName + ";"); } if (!imports.isEmpty()) { writer.println(); } String extendsString = extendsClass == null ? "" : " extends " + extendsClass.name; writer.println("public class " + type.className + extendsString + " {"); for (FieldRef field : fields) { writer.println(); writer.println(" " + field.toJava() + ";"); } for (Constructor constructor : constructors) { writer.println(); for (String s : constructor.write()) { writer.println(s); } } for (MethodRef method : methods) { writer.println(); write(writer, method); } writer.println("}"); } private void write(PrintWriter writer, MethodRef method) { String returnString; if (method.returnType == TypeRef.VOID) { returnString = "void"; } else { returnString = method.returnType.name; } List parameters = new ArrayList<>(); for (ParameterRef p : method.parameters) { parameters.add("final " + p.klass.name + " " + p.name); } writer.print(" " + Modifier.toString(method.modifiers) + " " + returnString + " " + method.name + "(" + collectionToDelimitedString(parameters, ", ") + ")"); if (method.exceptions.isEmpty()) { writer.println(" {"); } else { writer.println(" throws"); ArrayList typeRefs = new ArrayList<>(method.exceptions); for (int i = 0; i < typeRefs.size(); i++) { TypeRef e = typeRefs.get(i); writer.print(" " + e.name); if (i < typeRefs.size() - 1) { writer.println(","); } else { writer.println(" {"); } } } for (String s : method.body) { writer.print(" "); writer.println(s); } writer.println(" }"); } }