From d0ed4ad157e72e7bd47d0b3d72e6938e9e6b2025 Mon Sep 17 00:00:00 2001 From: Bipinkumar27 Date: Tue, 12 Sep 2023 19:21:39 +0530 Subject: [PATCH] JAVA-20500: Changes made for Merge annotations module with google-auto-project --- google-auto-project/README.md | 2 + .../annotation-processing/pom.xml | 28 ++++ .../processor/BuilderProcessor.java | 123 ++++++++++++++++++ .../annotation/processor/BuilderProperty.java | 8 ++ .../src/main/resources/logback.xml | 13 ++ google-auto-project/annotation-user/pom.xml | 23 ++++ .../java/com/baeldung/annotation/Person.java | 29 +++++ .../src/main/resources/logback.xml | 13 ++ .../annotation/PersonBuilderUnitTest.java | 19 +++ google-auto-project/pom.xml | 7 + pom.xml | 2 - 11 files changed, 265 insertions(+), 2 deletions(-) create mode 100644 google-auto-project/annotation-processing/pom.xml create mode 100644 google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java create mode 100644 google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java create mode 100644 google-auto-project/annotation-processing/src/main/resources/logback.xml create mode 100644 google-auto-project/annotation-user/pom.xml create mode 100644 google-auto-project/annotation-user/src/main/java/com/baeldung/annotation/Person.java create mode 100644 google-auto-project/annotation-user/src/main/resources/logback.xml create mode 100644 google-auto-project/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderUnitTest.java diff --git a/google-auto-project/README.md b/google-auto-project/README.md index d45a113a8f..44dd6c5d61 100644 --- a/google-auto-project/README.md +++ b/google-auto-project/README.md @@ -8,3 +8,5 @@ This module contains articles about automatic code generation - [Introduction to AutoFactory](https://www.baeldung.com/autofactory) - [Google AutoService](https://www.baeldung.com/google-autoservice) - [Defensive Copies for Collections Using AutoValue](https://www.baeldung.com/autovalue-defensive-copies) +- [Java Annotation Processing and Creating a Builder](https://www.baeldung.com/java-annotation-processing-builder) + diff --git a/google-auto-project/annotation-processing/pom.xml b/google-auto-project/annotation-processing/pom.xml new file mode 100644 index 0000000000..5c872c2059 --- /dev/null +++ b/google-auto-project/annotation-processing/pom.xml @@ -0,0 +1,28 @@ + + + 4.0.0 + annotation-processing + annotation-processing + + + com.baeldung + google-auto-project + 1.0 + + + + + com.google.auto.service + auto-service + ${auto-service.version} + provided + + + + + 1.0-rc2 + + + \ No newline at end of file diff --git a/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java b/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java new file mode 100644 index 0000000000..18d8f9a8a9 --- /dev/null +++ b/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProcessor.java @@ -0,0 +1,123 @@ +package com.baeldung.annotation.processor; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.ExecutableType; +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; + +import com.google.auto.service.AutoService; + +@SupportedAnnotationTypes("com.baeldung.annotation.processor.BuilderProperty") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +@AutoService(Processor.class) +public class BuilderProcessor extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + for (TypeElement annotation : annotations) { + + Set annotatedElements = roundEnv.getElementsAnnotatedWith(annotation); + + Map> annotatedMethods = annotatedElements.stream().collect(Collectors.partitioningBy(element -> ((ExecutableType) element.asType()).getParameterTypes().size() == 1 && element.getSimpleName().toString().startsWith("set"))); + + List setters = annotatedMethods.get(true); + List otherMethods = annotatedMethods.get(false); + + otherMethods.forEach(element -> processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@BuilderProperty must be applied to a setXxx method with a single argument", element)); + + if (setters.isEmpty()) { + continue; + } + + String className = ((TypeElement) setters.get(0).getEnclosingElement()).getQualifiedName().toString(); + + Map setterMap = setters.stream().collect(Collectors.toMap(setter -> setter.getSimpleName().toString(), setter -> ((ExecutableType) setter.asType()).getParameterTypes().get(0).toString())); + + try { + writeBuilderFile(className, setterMap); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + return true; + } + + private void writeBuilderFile(String className, Map setterMap) throws IOException { + + String packageName = null; + int lastDot = className.lastIndexOf('.'); + if (lastDot > 0) { + packageName = className.substring(0, lastDot); + } + + String simpleClassName = className.substring(lastDot + 1); + String builderClassName = className + "Builder"; + String builderSimpleClassName = builderClassName.substring(lastDot + 1); + + JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName); + try (PrintWriter out = new PrintWriter(builderFile.openWriter())) { + + if (packageName != null) { + out.print("package "); + out.print(packageName); + out.println(";"); + out.println(); + } + + out.print("public class "); + out.print(builderSimpleClassName); + out.println(" {"); + out.println(); + + out.print(" private "); + out.print(simpleClassName); + out.print(" object = new "); + out.print(simpleClassName); + out.println("();"); + out.println(); + + out.print(" public "); + out.print(simpleClassName); + out.println(" build() {"); + out.println(" return object;"); + out.println(" }"); + out.println(); + + setterMap.entrySet().forEach(setter -> { + String methodName = setter.getKey(); + String argumentType = setter.getValue(); + + out.print(" public "); + out.print(builderSimpleClassName); + out.print(" "); + out.print(methodName); + + out.print("("); + + out.print(argumentType); + out.println(" value) {"); + out.print(" object."); + out.print(methodName); + out.println("(value);"); + out.println(" return this;"); + out.println(" }"); + out.println(); + }); + + out.println("}"); + + } + } + +} diff --git a/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java b/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java new file mode 100644 index 0000000000..84fcc73850 --- /dev/null +++ b/google-auto-project/annotation-processing/src/main/java/com/baeldung/annotation/processor/BuilderProperty.java @@ -0,0 +1,8 @@ +package com.baeldung.annotation.processor; + +import java.lang.annotation.*; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.SOURCE) +public @interface BuilderProperty { +} diff --git a/google-auto-project/annotation-processing/src/main/resources/logback.xml b/google-auto-project/annotation-processing/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/google-auto-project/annotation-processing/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/google-auto-project/annotation-user/pom.xml b/google-auto-project/annotation-user/pom.xml new file mode 100644 index 0000000000..c21a4ca03d --- /dev/null +++ b/google-auto-project/annotation-user/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + annotation-user + annotation-user + + + com.baeldung + google-auto-project + 1.0 + + + + + com.baeldung + annotation-processing + ${project.parent.version} + + + + \ No newline at end of file diff --git a/google-auto-project/annotation-user/src/main/java/com/baeldung/annotation/Person.java b/google-auto-project/annotation-user/src/main/java/com/baeldung/annotation/Person.java new file mode 100644 index 0000000000..23787ba4f4 --- /dev/null +++ b/google-auto-project/annotation-user/src/main/java/com/baeldung/annotation/Person.java @@ -0,0 +1,29 @@ +package com.baeldung.annotation; + +import com.baeldung.annotation.processor.BuilderProperty; + +public class Person { + + private int age; + + private String name; + + public int getAge() { + return age; + } + + @BuilderProperty + public void setAge(int age) { + this.age = age; + } + + public String getName() { + return name; + } + + @BuilderProperty + public void setName(String name) { + this.name = name; + } + +} diff --git a/google-auto-project/annotation-user/src/main/resources/logback.xml b/google-auto-project/annotation-user/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/google-auto-project/annotation-user/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/google-auto-project/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderUnitTest.java b/google-auto-project/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderUnitTest.java new file mode 100644 index 0000000000..d5f758089a --- /dev/null +++ b/google-auto-project/annotation-user/src/test/java/com/baeldung/annotation/PersonBuilderUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.annotation; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class PersonBuilderUnitTest { + + @Test + public void whenBuildPersonWithBuilder_thenObjectHasPropertyValues() { + + Person person = new PersonBuilder().setAge(25).setName("John").build(); + + assertEquals(25, person.getAge()); + assertEquals("John", person.getName()); + + } + +} diff --git a/google-auto-project/pom.xml b/google-auto-project/pom.xml index 839ccabc5f..034fea5aad 100644 --- a/google-auto-project/pom.xml +++ b/google-auto-project/pom.xml @@ -6,6 +6,8 @@ google-auto-project 1.0 google-auto-project + pom + com.baeldung @@ -13,6 +15,11 @@ 1.0.0-SNAPSHOT + + annotation-processing + annotation-user + + com.google.auto.value diff --git a/pom.xml b/pom.xml index 1618ac684f..87308ff0bd 100644 --- a/pom.xml +++ b/pom.xml @@ -812,7 +812,6 @@ akka-modules - annotations httpclient-simple antlr apache-kafka @@ -1086,7 +1085,6 @@ akka-modules - annotations antlr apache-kafka apache-kafka-2