Skip to content

Instantly share code, notes, and snippets.

@edefazio
Last active February 19, 2019 18:38
Show Gist options
  • Save edefazio/e3cccdfd4cf5289c924c22227b161743 to your computer and use it in GitHub Desktop.
Save edefazio/e3cccdfd4cf5289c924c22227b161743 to your computer and use it in GitHub Desktop.
compare the JavaPoet and draft.java APIs for generating .java code
package draft.tutorial.usecase;
import com.squareup.javapoet.*;
import draft.java.*;
import draft.java.macro.*;
import draft.java.runtime.*;
import draft.java.template.$method;
import java.io.IOException;
import java.util.*;
import javax.lang.model.element.Modifier;
import junit.framework.TestCase;
import java.util.logging.LogRecord;
/**
* Compare and contract the ability of JavaPoet and draft.java
* for generating code (the examples are from: https://github.com/square/javapoet
*
* @author Eric
*/
public class JavaPoet_v_draft extends TestCase {
public void test1JavaPoet()throws IOException {
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
}
public void test1Draft(){
_class _c = _class.of("com.example.helloworld.HelloWorld")
.main( () ->System.out.println("Hello JavaPoet!") );
System.out.println( _c );
}
public void test2JavaPoet(){
MethodSpec main = MethodSpec.methodBuilder("main")
.addCode(""
+ "int total = 0;\n"
+ "for(int i=0; i< 10; i++){\n"
+ " total += i;\n"
+ "}\n" )
.build();
System.out.println( main );
}
public void test2Draft(){
_method _main = _method.of("main", ()-> {
int total = 0;
for(int i=0;i<10;i++){
total += i;
}
});
System.out.println( _main );
}
public void test3JavaPoet(){
MethodSpec main = MethodSpec.methodBuilder("main")
.addStatement("int total = 0")
.beginControlFlow("for (int i = 0; i < 10; i++)")
.addStatement("total += i")
.endControlFlow()
.build();
System.out.println( main );
}
public void test3Draft(){
_method _main = _method.of(new Object(){
void main(){
int total = 0;
for(int i = 0; i < 10; i++){
total += i;
}
}
});
System.out.println( main );
}
private MethodSpec computeRange(String name, int from, int to, String op) {
return MethodSpec.methodBuilder(name)
.returns(int.class)
.addStatement("int result = 1")
.beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")
.addStatement("result = result " + op + " i")
.endControlFlow()
.addStatement("return result")
.build();
}
public void test4JavaPoet(){
System.out.println( computeRange("multiply10to20", 10, 20, "*") );
}
private $method $computeRange = $method.of(new Object(){
public int $name$(){
int result = 1;
for(int i=$from$;i<$to$;i++){
result = result * i;
}
return result;
}
int $from$, $to$;
}).$("*", "op");
public void test4Draft(){
System.out.println($computeRange.fill("multiply10to20",10,20,"*"));
}
MethodSpec main = MethodSpec.methodBuilder("main")
.addStatement("long now = $T.currentTimeMillis()", System.class)
.beginControlFlow("if ($T.currentTimeMillis() < now)", System.class)
.addStatement("$T.out.println($S)", System.class, "Time travelling, woo hoo!")
.nextControlFlow("else if ($T.currentTimeMillis() == now)", System.class)
.addStatement("$T.out.println($S)", System.class, "Time stood still!")
.nextControlFlow("else")
.addStatement("$T.out.println($S)", System.class, "Ok, time still moving forward")
.endControlFlow()
.build();
public void test5JavaPoet(){
System.out.println( main );
}
public void test5Draft(){
_method _m = _method.of(new Object(){
void main() {
long now = System.currentTimeMillis();
if(System.currentTimeMillis() < now){
System.out.println("Time travelling, woo hoo!");
} else if (System.currentTimeMillis() == now) {
System.out.println("Time stood still!");
} else {
System.out.println("Ok, time still moving forward");
}
}
});
System.out.println( _m );
}
public void test6JavaPoet(){
MethodSpec main = MethodSpec.methodBuilder("main")
.beginControlFlow("try")
.addStatement("throw new Exception($S)", "Failed")
.nextControlFlow("catch ($T e)", Exception.class)
.addStatement("throw new $T(e)", RuntimeException.class)
.endControlFlow()
.build();
System.out.println( main );
}
public void test6Draft(){
_method _main = _method.of( new Object(){
void main() {
try {
throw new Exception("Failed");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
});
System.out.println( _main );
}
public void test7JavaPoet() throws IOException {
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(whatsMyName("slimShady"))
.addMethod(whatsMyName("eminem"))
.addMethod(whatsMyName("marshallMathers"))
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
}
private static MethodSpec whatsMyName(String name) {
return MethodSpec.methodBuilder(name)
.returns(String.class)
.addStatement("return $S", name)
.build();
}
public void test7Draft(){
$method $whatsMyName = $method.of( new Object(){
String $name$(){
return "$name$";
}
});
_class _h = _class.of("com.example.helloworld.HelloWorld")
.setPublic().setFinal()
.add($whatsMyName.fill("slimShady"),
$whatsMyName.fill("eminem"),
$whatsMyName.fill("marshallMathers"));
System.out.println( _h );
}
public void test8JavaPoet() throws IOException {
MethodSpec today = MethodSpec.methodBuilder("today")
.returns(Date.class)
.addStatement("return new $T()", Date.class)
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(today)
.build();
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
.build();
javaFile.writeTo(System.out);
}
// NOTE: because we define the body of the Class via
// an anonymous Object, we inferred the imports (specifically Date.class)
public void test8Draft(){
_class _c = _class.of("com.example.helloworld.HelloWorld", new Object(){
public Date today(){
return new Date();
}
});
System.out.println(_c );
_javac.of(_c);
}
public void test9JavaPoet(){
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);
MethodSpec beyond = MethodSpec.methodBuilder("beyond")
.returns(listOfHoverboards)
.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("result.add(new $T())", hoverboard)
.addStatement("return result")
.build();
System.out.println(beyond);
}
_class _hoverboard = _class.of("com.mattel.Hoverboard", new Object(){
public List<Hoverboard> beyond(){
List<Hoverboard> result = new ArrayList<>();
result.add(new Hoverboard());
result.add(new Hoverboard());
result.add(new Hoverboard());
return result;
}
@_remove class Hoverboard{}
}).imports(ArrayList.class);
public void test9Draft(){
//build, compile & load, create new instance & call beyond method
assertEquals(3, ((List)_proxy.of( _hoverboard ).call("beyond")).size());
//verify we created and return (3) new Hoverboards
}
// Import Static
public void test10JavaPoet(){
ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);
MethodSpec beyond = MethodSpec.methodBuilder("beyond")
.returns(listOfHoverboards)
.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
.addStatement("result.add($T.createNimbus(2000))", hoverboard)
.addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard)
.addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards)
.addStatement("$T.sort(result)", Collections.class)
.addStatement("return result.isEmpty() ? $T.emptyList() : result", Collections.class)
.build();
TypeSpec hello = TypeSpec.classBuilder("HelloWorld")
.addMethod(beyond)
.build();
JavaFile jf = JavaFile.builder("com.example.helloworld", hello)
.addStaticImport(hoverboard, "createNimbus")
.addStaticImport(namedBoards, "*")
.addStaticImport(Collections.class, "*")
.build();
System.out.println( jf );
}
// Implicit Type
public void test10Draft(){
_class _c = _class.of("com.example.helloworld.HelloWorld", new Object(){
@_remove class Hoverboard{}
List<Hoverboard> beyond() {
List<Hoverboard> result = new ArrayList<>();
result.add(new Hoverboard());
result.add(new Hoverboard());
result.add(new Hoverboard());
return result;
}
}).imports(_hoverboard).imports(ArrayList.class);
_javac.of(_hoverboard, _c);
}
//Import Static
public void test11JavaPoet(){
ClassName namedBoards = ClassName.get("com.mattel", "Hoverboard", "Boards");
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
ClassName list = ClassName.get("java.util", "List");
ClassName arrayList = ClassName.get("java.util", "ArrayList");
TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);
MethodSpec beyond = MethodSpec.methodBuilder("beyond")
.returns(listOfHoverboards)
.addStatement("$T result = new $T<>()", listOfHoverboards, arrayList)
.addStatement("result.add($T.createNimbus(2000))", hoverboard)
.addStatement("result.add($T.createNimbus(\"2001\"))", hoverboard)
.addStatement("result.add($T.createNimbus($T.THUNDERBOLT))", hoverboard, namedBoards)
.addStatement("$T.sort(result)", Collections.class)
.addStatement("return result.isEmpty() ? $T.emptyList() : result", Collections.class)
.build();
TypeSpec hello = TypeSpec.classBuilder("HelloWorld")
.addMethod(beyond)
.build();
JavaFile jf = JavaFile.builder("com.example.helloworld", hello)
.addStaticImport(hoverboard, "createNimbus")
.addStaticImport(namedBoards, "*")
.addStaticImport(Collections.class, "*")
.build();
}
public void test11Draft(){
_class _c = _class.of("com.example.helloworld.HelloWorld")
.method(
"List<Hoverboard> beyond() {",
"List<Hoverboard> result = new ArrayList<>();",
"result.add(createNimbus(2000));",
"result.add(createNimbus(\"2001\"));",
"result.add(createNimbus(THUNDERBOLT));",
"sort(result);",
"return result.isEmpty() ? emptyList() : result;",
"}")
.importStatic(Collections.class.getCanonicalName()+".*",
"com.mattel.Hoverboard.Boards.*",
"com.mattel.Hoverboard.createNimbus.*");
System.out.println( _c);
}
/*
public void test11Draft(){
_class _c = _class.of("com.example.helloworld.HelloWorld", new Object(){
List<Hoverboard> beyond() {
List<Hoverboard> result = new ArrayList<>();
result.add(createNimbus(2000));
result.add(createNimbus("2001"));
result.add(createNimbus(THUNDERBOLT));
sort(result);
return result.isEmpty() ? emptyList() : result;
}
@_remove class Hoverboard implements Comparable {
public int compareTo(Object o){ return 1;}
}
@_remove public Hoverboard createNimbus( int val ){ return null; }
@_remove public Hoverboard createNimbus( String val ){ return null; }
@_remove public Hoverboard createNimbus( Hoverboard board ){ return null; }
@_remove Hoverboard THUNDERBOLT = new Hoverboard();
}).importStatic(Collections.class.getCanonicalName()+".*",
"com.mattel.Hoverboard.Boards.*",
"com.mattel.Hoverboard.createNimbus.*");
System.out.println( _c);
}
*/
public void test12JavaPoet(){
MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit")
.addParameter(int.class, "i")
.returns(char.class)
.addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')")
.build();
MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex")
.addParameter(int.class, "b")
.returns(String.class)
.addStatement("char[] result = new char[2]")
.addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit)
.addStatement("result[1] = $N(b & 0xf)", hexDigit)
.addStatement("return new String(result)")
.build();
System.out.println( byteToHex );
}
public void test12Draft(){
_method _hexDigit = _method.of(new Object(){
public char hexDigit(int i) {
return (char) (i < 10 ? i + '0' : i - 10 + 'a');
}
});
_method _byteToHex = _method.of(new Object(){
public String byteToHex(int b) {
char[] result = new char[2];
result[0] = hexDigit((b >>> 4) & 0xf);
result[1] = hexDigit(b & 0xf);
return new String(result);
}
@_remove char hexDigit(int i){ return 0; }
});
_class _c = _class.of( "C" ).add( _hexDigit, _byteToHex );
assertEquals("0f", (String)_proxy.of(_c).call("byteToHex", 15 ) );
}
public void test13JavaPoet(){
MethodSpec flux = MethodSpec.methodBuilder("flux")
.addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED)
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addMethod(flux)
.build();
System.out.println( helloWorld );
}
public void test13Draft(){
_class _c = _class.of("public abstract class HelloWorld")
.method("protected abstract void flux();");
System.out.println( _c );
}
//Constructors
public void test14JavaPoet(){
MethodSpec flux = MethodSpec.constructorBuilder()
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "greeting")
.addStatement("this.$N = $N", "greeting", "greeting")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(String.class, "greeting", Modifier.PRIVATE, Modifier.FINAL)
.addMethod(flux)
.build();
System.out.println( helloWorld );
}
public void test14Draft(){
_class _c = _class.of( "HelloWorld", new Object(){
private @_final String greeting;
@_ctor public void HelloWorld(String greeting) {
this.greeting = greeting;
}
});
System.out.println( _c );
}
public void test15JavaPoet(){
ParameterSpec android = ParameterSpec.builder(String.class, "android")
.addModifiers(Modifier.FINAL)
.build();
MethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords")
.addParameter(android)
.addParameter(String.class, "robot", Modifier.FINAL)
.build();
System.out.println( welcomeOverlords );
}
public void test15Draft(){
_parameter _p = _parameter.of(String.class, "android").setFinal()
.annotate("@Nullable");
_method _welcomeOverlords = _method.of("welcomeOverlords")
.addParameter(_p)
.addParameter("final String robot");
System.out.println( _welcomeOverlords );
}
/**
* https://github.com/square/javapoet#fields
*/
public void test16JavaPoet(){
FieldSpec android = FieldSpec.builder(String.class, "android")
.addModifiers(Modifier.PRIVATE, Modifier.FINAL)
.initializer("$S + $L", "Lollipop v.", 5.0d)
.build();
System.out.println( android );
}
public void test16Draft(){
_field _android = _field.of("private final String android;")
.init(()-> "Lollipop v." + 5.0d );
System.out.println( _android );
}
/* https://github.com/square/javapoet#interfaces */
public void test17JavaPoet(){
TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC)
.addField(FieldSpec.builder(String.class, "ONLY_THING_THAT_IS_CONSTANT")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
.initializer("$S", "change")
.build())
.addMethod(MethodSpec.methodBuilder("beep")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.build())
.build();
System.out.println(helloWorld);
}
public void test17Draft(){
_interface _helloWorld = _interface.of("HelloWorld", new Object(){
public @_static @_final String ONLY_THING_THAT_IS_CONSTANT = "change";
@_abstract void beep(){}
});
System.out.println( _helloWorld );
_javac.of( _helloWorld );
}
/* https://github.com/square/javapoet#enums */
public void test18JavaPoet(){
TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
.addModifiers(Modifier.PUBLIC)
.addEnumConstant("ROCK")
.addEnumConstant("SCISSORS")
.addEnumConstant("PAPER")
.build();
System.out.println( helloWorld );
}
public void test18Draft(){
_enum _e = _enum.of("Roshambo")
.constants("ROCK","PAPER","SCISSORS");
System.out.println( _e );
}
public void test19JavaPoet(){
TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")
.addModifiers(Modifier.PUBLIC)
.addEnumConstant("ROCK", TypeSpec.anonymousClassBuilder("$S", "fist")
.addMethod(MethodSpec.methodBuilder("toString")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addStatement("return $S", "avalanche!")
.returns(String.class)
.build())
.build())
.addEnumConstant("SCISSORS", TypeSpec.anonymousClassBuilder("$S", "peace")
.build())
.addEnumConstant("PAPER", TypeSpec.anonymousClassBuilder("$S", "flat")
.build())
.addField(String.class, "handsign", Modifier.PRIVATE, Modifier.FINAL)
.addMethod(MethodSpec.constructorBuilder()
.addParameter(String.class, "handsign")
.addStatement("this.$N = $N", "handsign", "handsign")
.build())
.build();
System.out.println(helloWorld);
}
public void test19Draft(){
_enum _e = _enum.of("Roshambo")
.field("private final String handSign;")
.apply(_autoConstructor.$)
.constant("ROCK(\"fist\")", new Object(){
@Override
public String toString(){
return "avalanche!";
}
})
.constant("SCISSORS(\"peace\")")
.constant("PAPER(\"flat\")");
System.out.println( _e );
_javac.of(_e);
}
/* https://github.com/square/javapoet#anonymous-inner-classes */
public void test20JavaPoet(){
TypeSpec comparator = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(Comparator.class, String.class))
.addMethod(MethodSpec.methodBuilder("compare")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.addParameter(String.class, "a")
.addParameter(String.class, "b")
.returns(int.class)
.addStatement("return $N.length() - $N.length()", "a", "b")
.build())
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addMethod(MethodSpec.methodBuilder("sortByLength")
.addParameter(ParameterizedTypeName.get(List.class, String.class), "strings")
.addStatement("$T.sort($N, $L)", Collections.class, "strings", comparator)
.build())
.build();
System.out.println( helloWorld );
}
public void test20Draft(){
_class _c = _class.of("class HelloWorld", new Object() {
public void sortByLength(List<String> strings) {
Collections.sort(strings, new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.length() - b.length();
}
});
}
}).imports(Collections.class, Comparator.class, List.class);
System.out.println(_c);
_javac.of( _c );
}
/* https://github.com/square/javapoet#annotations */
public void test21JavaPoet(){
MethodSpec toString = MethodSpec.methodBuilder("toString")
.addAnnotation(Override.class)
.returns(String.class)
.addModifiers(Modifier.PUBLIC)
.addStatement("return $S", "Hoverboard")
.build();
System.out.println(toString);
}
public void test21Draft(){
_method _m = _method.of(new Object(){
@Override
public String toString(){
return "Hoverboard";
}
});
//or
_m.annotate(Override.class);
}
class LogReceipt{
}
@interface Headers{
}
public void test22JavaPoet(){
MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotation(AnnotationSpec.builder(Headers.class)
.addMember("accept", "$S", "application/json; charset=utf-8")
.addMember("userAgent", "$S", "Square Cash")
.build())
.addParameter(LogRecord.class, "logRecord")
.returns(LogReceipt.class)
.build();
System.out.println( logRecord );
}
public void test22Draft(){
_anno _a = _anno.of(Headers.class)
.addAttr("accept", "\"application/json; charset=utf-8\"")
.addAttr("userAgent","\"Square Cash\"");
_method _m = _method.of("public abstract LogReceipt recordEvent(LogRecord logRecord);")
.annotate(_a);
System.out.println( _m );
}
public void test23JavaPoet(){
MethodSpec logRecord = MethodSpec.methodBuilder("recordEvent")
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.addAnnotation(AnnotationSpec.builder(HeaderList.class)
.addMember("value", "$L", AnnotationSpec.builder(Header.class)
.addMember("name", "$S", "Accept")
.addMember("value", "$S", "application/json; charset=utf-8")
.build())
.addMember("value", "$L", AnnotationSpec.builder(Header.class)
.addMember("name", "$S", "User-Agent")
.addMember("value", "$S", "Square Cash")
.build())
.build())
.addParameter(LogRecord.class, "logRecord")
.returns(LogReceipt.class)
.build();
System.out.println(logRecord);
}
public @interface HeaderList{
Header[] value();
}
public @interface Header{
String name();
String value();
}
public void test23Draft(){
_anno _a = _anno.of(new Object(){
@HeaderList({
@Header(name="Accept", value="application/json; charset=utf-8"),
@Header(name="User-Agent", value="Square Cash"),
})
class C{}
});
_method _m = _method.of("public abstract LogReceipt recordEvent(LogRecord logRecord);")
.annotate(_a);
System.out.println( _m );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment