move annotation processor example
This commit is contained in:
14
build-all.sh
14
build-all.sh
@@ -82,6 +82,20 @@ build_maven_module() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if [[ "$MODULE" == "module7" ]]
|
||||
then
|
||||
# ADD NEW MODULES HERE
|
||||
# (add new modules above the rest so you get quicker feedback if it fails)
|
||||
build_maven_module "core-java/annotation-processing/introduction-to-annotations"
|
||||
|
||||
echo ""
|
||||
echo "+++"
|
||||
echo "+++ MODULE 7 SUCCESSFUL"
|
||||
echo "+++"
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$MODULE" == "module6" ]]
|
||||
then
|
||||
# ADD NEW MODULES HERE
|
||||
|
||||
Binary file not shown.
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AnnotationProcessorDemo</artifactId>
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<artifactId>annotation-processor</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.auto.service</groupId>
|
||||
<artifactId>auto-service</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.squareup/javapoet -->
|
||||
<dependency>
|
||||
<groupId>com.squareup</groupId>
|
||||
<artifactId>javapoet</artifactId>
|
||||
<version>1.9.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>1.9</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,11 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Builder {
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.squareup.javapoet.*;
|
||||
import org.apache.commons.text.CaseUtils;
|
||||
|
||||
import javax.annotation.processing.*;
|
||||
import javax.lang.model.SourceVersion;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.Modifier;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
import javax.lang.model.util.Elements;
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SupportedAnnotationTypes("com.reflectoring.annotation.processor.Builder")
|
||||
@SupportedSourceVersion(SourceVersion.RELEASE_11)
|
||||
@AutoService(Processor.class)
|
||||
public class BuilderProcessor extends AbstractProcessor {
|
||||
|
||||
private Filer filer;
|
||||
private Messager messager;
|
||||
private Elements elementUtils;
|
||||
|
||||
@Override
|
||||
public synchronized void init(ProcessingEnvironment processingEnv) {
|
||||
|
||||
super.init(processingEnv);
|
||||
filer = processingEnv.getFiler();
|
||||
messager = processingEnv.getMessager();
|
||||
elementUtils = processingEnv.getElementUtils();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
||||
|
||||
for (Element typeElement : roundEnv.getElementsAnnotatedWith(Builder.class)) {
|
||||
|
||||
List<Element> fieldElements = typeElement.getEnclosedElements().stream().filter(e -> ElementKind.FIELD.equals(e.getKind())).collect(
|
||||
Collectors.toList());
|
||||
|
||||
String packageName = elementUtils.getPackageOf(typeElement).getQualifiedName().toString();
|
||||
String className = typeElement.getSimpleName().toString();
|
||||
String builderName = String.format("%sBuilder", typeElement.getSimpleName().toString());
|
||||
String classVariableName = CaseUtils.toCamelCase(typeElement.getSimpleName().toString(), false, '_');
|
||||
|
||||
try {
|
||||
//writeBuilderClass(packageName, className, classVariableName, builderName, fieldElements);
|
||||
|
||||
writeJavaPoetBuilderClass(packageName, className, classVariableName, builderName, fieldElements, typeElement);
|
||||
} catch (IOException e) {
|
||||
messager.printMessage(Diagnostic.Kind.ERROR, "Failed to write file for element", typeElement);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getBaseName(String name) {
|
||||
|
||||
int lastPeriodIndex = name.lastIndexOf('.');
|
||||
if (lastPeriodIndex > 0) {
|
||||
name = name.substring(lastPeriodIndex + 1);
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private void writeBuilderClass(String packageName, String className, String classVariableName, String builderName,
|
||||
List<Element> fieldElements) throws IOException {
|
||||
|
||||
JavaFileObject builder = processingEnv.getFiler().createSourceFile(builderName);
|
||||
|
||||
try (PrintWriter out = new PrintWriter(builder.openWriter())) {
|
||||
|
||||
// Write the Package name
|
||||
out.print("package ");
|
||||
out.print(packageName);
|
||||
out.println(";");
|
||||
out.println();
|
||||
|
||||
// Write the Class name
|
||||
out.print("public final class ");
|
||||
out.print(builderName);
|
||||
out.println(" {");
|
||||
out.println();
|
||||
|
||||
// Write the Field names
|
||||
for (Element fieldElement : fieldElements) {
|
||||
|
||||
TypeMirror typeMirror = fieldElement.asType();
|
||||
|
||||
String fieldTypeName = getBaseName(typeMirror.toString());
|
||||
String fieldName = getBaseName(fieldElement.getSimpleName().toString());
|
||||
|
||||
out.print("private ");
|
||||
out.print(fieldTypeName);
|
||||
out.print(" ");
|
||||
out.print(fieldName);
|
||||
out.print(";");
|
||||
out.println();
|
||||
}
|
||||
|
||||
out.println();
|
||||
|
||||
// Write the Setters
|
||||
for (Element fieldElement : fieldElements) {
|
||||
|
||||
TypeMirror typeMirror = fieldElement.asType();
|
||||
|
||||
String fieldTypeName = getBaseName(typeMirror.toString());
|
||||
String fieldName = getBaseName(fieldElement.getSimpleName().toString());
|
||||
|
||||
out.print("public ");
|
||||
out.print(" ");
|
||||
out.print(builderName);
|
||||
out.print(" ");
|
||||
out.print(fieldName);
|
||||
out.print("(");
|
||||
out.print(fieldTypeName);
|
||||
out.print(" ");
|
||||
out.print(fieldName);
|
||||
out.print(") {");
|
||||
out.println();
|
||||
out.print(" this.");
|
||||
out.print(fieldName);
|
||||
out.print(" = ");
|
||||
out.print(fieldName);
|
||||
out.print(";");
|
||||
out.println();
|
||||
out.print(" return this;");
|
||||
out.println();
|
||||
out.print("}");
|
||||
out.println();
|
||||
out.println();
|
||||
}
|
||||
|
||||
// Write the build function
|
||||
out.print("public ");
|
||||
out.print(" ");
|
||||
out.print(className);
|
||||
out.print(" build() {");
|
||||
out.println();
|
||||
out.print(" ");
|
||||
out.print(className);
|
||||
out.print(" ");
|
||||
out.print(classVariableName);
|
||||
out.print(" = new ");
|
||||
out.print(className);
|
||||
out.print("();");
|
||||
out.println();
|
||||
|
||||
for (Element fieldElement : fieldElements) {
|
||||
|
||||
TypeMirror typeMirror = fieldElement.asType();
|
||||
|
||||
String fieldTypeName = getBaseName(typeMirror.toString());
|
||||
String fieldName = getBaseName(fieldElement.getSimpleName().toString());
|
||||
|
||||
out.print(" ");
|
||||
out.print(classVariableName);
|
||||
out.print(".set");
|
||||
out.print(CaseUtils.toCamelCase(fieldName, true, '_'));
|
||||
out.print("(this.");
|
||||
out.print(fieldName);
|
||||
out.println(");");
|
||||
}
|
||||
|
||||
out.println();
|
||||
out.print(" return ");
|
||||
out.print(classVariableName);
|
||||
out.print(";");
|
||||
out.println();
|
||||
out.println(" }");
|
||||
out.println("}");
|
||||
}
|
||||
}
|
||||
|
||||
private void writeJavaPoetBuilderClass(String packageName, String className, String classVariableName, String builderName,
|
||||
List<Element> fieldElements, Element typeElement) throws IOException {
|
||||
|
||||
ClassName builderType = ClassName.get(packageName, builderName);
|
||||
|
||||
List<FieldSpec> fields = new ArrayList<>(fieldElements.size());
|
||||
List<MethodSpec> fieldSetters = new ArrayList<>(fieldElements.size());
|
||||
|
||||
// Generate the fields and field setters
|
||||
generateFieldsAndSetters(fields, fieldSetters, fieldElements, builderType);
|
||||
|
||||
TypeName targetType = TypeName.get(typeElement.asType());
|
||||
|
||||
// Generate the build method
|
||||
MethodSpec buildMethod = generateBuildMethod(targetType, classVariableName, fields);
|
||||
|
||||
TypeSpec builder = TypeSpec.classBuilder(builderType)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
|
||||
.addFields(fields)
|
||||
.addMethods(fieldSetters)
|
||||
.addMethod(buildMethod).build();
|
||||
|
||||
JavaFile file = JavaFile.builder(builderType.packageName(), builder.toBuilder().build()).build();
|
||||
|
||||
file.writeTo(filer);
|
||||
}
|
||||
|
||||
private void generateFieldsAndSetters(List<FieldSpec> fields, List<MethodSpec> fieldSetters, List<Element> fieldElements, ClassName builderType){
|
||||
|
||||
for (Element fieldElement : fieldElements) {
|
||||
|
||||
TypeName typeName = TypeName.get(fieldElement.asType());
|
||||
String fieldName = getBaseName(fieldElement.getSimpleName().toString());
|
||||
|
||||
fields.add(FieldSpec.builder(typeName, fieldName, Modifier.PRIVATE).build());
|
||||
|
||||
fieldSetters.add(
|
||||
MethodSpec.methodBuilder(fieldName)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(builderType)
|
||||
.addParameter(typeName, fieldName)
|
||||
.addStatement("this.$N = $N", fieldName, fieldName)
|
||||
.addStatement("return this").build());
|
||||
}
|
||||
}
|
||||
|
||||
private MethodSpec generateBuildMethod(TypeName targetType, String variableName, List<FieldSpec> fields) {
|
||||
|
||||
MethodSpec.Builder buildMethodBuilder = MethodSpec.methodBuilder("build")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.returns(targetType)
|
||||
.addStatement("$1T $2N = new $1T()", targetType, variableName);
|
||||
|
||||
for (FieldSpec field : fields) {
|
||||
|
||||
buildMethodBuilder.addStatement("$1N.set$2N(this.$3N)", variableName, CaseUtils.toCamelCase(field.name, true, '_'), field.name);
|
||||
}
|
||||
|
||||
buildMethodBuilder.addStatement("return $N", variableName);
|
||||
|
||||
return buildMethodBuilder.build();
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1 +0,0 @@
|
||||
com.reflectoring.annotation.processor.BuilderProcessor
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,5 +0,0 @@
|
||||
#Generated by Maven
|
||||
#Wed Jan 26 14:56:24 EST 2022
|
||||
groupId=com.reflectoring.annotation.processor
|
||||
artifactId=annotation-processor
|
||||
version=1.0
|
||||
@@ -1,3 +0,0 @@
|
||||
META-INF\services\javax.annotation.processing.Processor
|
||||
com\reflectoring\annotation\processor\Builder.class
|
||||
com\reflectoring\annotation\processor\BuilderProcessor.class
|
||||
@@ -1,2 +0,0 @@
|
||||
D:\Documents\IntelliJ Projects\AnnotationProcessorDemo\annotation-processor\src\main\java\com\reflectoring\annotation\processor\Builder.java
|
||||
D:\Documents\IntelliJ Projects\AnnotationProcessorDemo\annotation-processor\src\main\java\com\reflectoring\annotation\processor\BuilderProcessor.java
|
||||
@@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>AnnotationProcessorDemo</artifactId>
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<version>1.0</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<version>1.0</version>
|
||||
<artifactId>core</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<artifactId>annotation-processor</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
public class Department {
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
public class Employee {
|
||||
|
||||
private int id;
|
||||
private String department;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDepartment() {
|
||||
return department;
|
||||
}
|
||||
|
||||
public void setDepartment(String department) {
|
||||
this.department = department;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.test;
|
||||
|
||||
import com.reflectoring.annotation.processor.Employee;
|
||||
|
||||
public class BuilderTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
Employee employee = new EmployeeBuilder()
|
||||
.department("Sales")
|
||||
.build();
|
||||
|
||||
System.out.println("Employee dept: " + employee.getDepartment());
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.test;
|
||||
|
||||
import com.reflectoring.annotation.processor.Department;
|
||||
|
||||
public final class DepartmentBuilder {
|
||||
|
||||
private int id;
|
||||
private String name;
|
||||
|
||||
public DepartmentBuilder id(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DepartmentBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Department build() {
|
||||
Department department = new Department();
|
||||
department.setId(this.id);
|
||||
department.setName(this.name);
|
||||
|
||||
return department;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.test;
|
||||
|
||||
import com.reflectoring.annotation.processor.Employee;
|
||||
|
||||
public final class EmployeeBuilder {
|
||||
|
||||
private int id;
|
||||
private String department;
|
||||
|
||||
public EmployeeBuilder id(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmployeeBuilder department(String department) {
|
||||
this.department = department;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Employee build() {
|
||||
Employee employee = new Employee();
|
||||
employee.setId(this.id);
|
||||
employee.setDepartment(this.department);
|
||||
|
||||
return employee;
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,26 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
import java.lang.String;
|
||||
|
||||
public final class DepartmentBuilder {
|
||||
private int id;
|
||||
|
||||
private String name;
|
||||
|
||||
public DepartmentBuilder id(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DepartmentBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Department build() {
|
||||
Department department = new Department();
|
||||
department.setId(this.id);
|
||||
department.setName(this.name);
|
||||
return department;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.reflectoring.annotation.processor;
|
||||
|
||||
import java.lang.String;
|
||||
|
||||
public final class EmployeeBuilder {
|
||||
private int id;
|
||||
|
||||
private String department;
|
||||
|
||||
public EmployeeBuilder id(int id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EmployeeBuilder department(String department) {
|
||||
this.department = department;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Employee build() {
|
||||
Employee employee = new Employee();
|
||||
employee.setId(this.id);
|
||||
employee.setDepartment(this.department);
|
||||
return employee;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
com\reflectoring\annotation\processor\Employee.class
|
||||
com\reflectoring\annotation\processor\Department.class
|
||||
com\reflectoring\annotation\processor\EmployeeBuilder.class
|
||||
com\reflectoring\annotation\processor\DepartmentBuilder.class
|
||||
@@ -1,2 +0,0 @@
|
||||
D:\Documents\IntelliJ Projects\AnnotationProcessorDemo\core\src\main\java\com\reflectoring\annotation\processor\Employee.java
|
||||
D:\Documents\IntelliJ Projects\AnnotationProcessorDemo\core\src\main\java\com\reflectoring\annotation\processor\Department.java
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.reflectoring.annotation.processor</groupId>
|
||||
<artifactId>AnnotationProcessorDemo</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.0</version>
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>annotation-processor</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user