Skip to content

Commit ea85fa9

Browse files
forketyforkpivovarit
authored andcommitted
Added samples for annotation processing article. (eugenp#705)
* Added annotation processing examples. Fixed core-java8 build on OS X * Moved projects to separate submodule
1 parent d1bd04d commit ea85fa9

File tree

11 files changed

+319
-14
lines changed

11 files changed

+319
-14
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>com.baeldung</groupId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
<artifactId>annotations</artifactId>
11+
<relativePath>../</relativePath>
12+
</parent>
13+
14+
<artifactId>annotation-processing</artifactId>
15+
16+
<properties>
17+
<auto-service.version>1.0-rc2</auto-service.version>
18+
<maven-compiler-plugin.version>3.5.1</maven-compiler-plugin.version>
19+
</properties>
20+
21+
<dependencies>
22+
23+
<dependency>
24+
<groupId>com.google.auto.service</groupId>
25+
<artifactId>auto-service</artifactId>
26+
<version>${auto-service.version}</version>
27+
<scope>provided</scope>
28+
</dependency>
29+
30+
</dependencies>
31+
32+
<build>
33+
34+
<plugins>
35+
36+
<plugin>
37+
<groupId>org.apache.maven.plugins</groupId>
38+
<artifactId>maven-compiler-plugin</artifactId>
39+
<version>${maven-compiler-plugin.version}</version>
40+
<configuration>
41+
<source>1.8</source>
42+
<target>1.8</target>
43+
</configuration>
44+
</plugin>
45+
46+
</plugins>
47+
48+
</build>
49+
50+
</project>
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package com.baeldung.annotation.processor;
2+
3+
import java.io.IOException;
4+
import java.io.PrintWriter;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Set;
8+
import java.util.stream.Collectors;
9+
import javax.annotation.processing.*;
10+
import javax.lang.model.SourceVersion;
11+
import javax.lang.model.element.Element;
12+
import javax.lang.model.element.TypeElement;
13+
import javax.lang.model.type.ExecutableType;
14+
import javax.tools.Diagnostic;
15+
import javax.tools.JavaFileObject;
16+
17+
import com.google.auto.service.AutoService;
18+
19+
@SupportedAnnotationTypes("com.baeldung.annotation.processor.BuilderProperty")
20+
@SupportedSourceVersion(SourceVersion.RELEASE_8)
21+
@AutoService(Processor.class)
22+
public class BuilderProcessor extends AbstractProcessor {
23+
24+
@Override
25+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
26+
for (TypeElement annotation : annotations) {
27+
28+
Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
29+
30+
Map<Boolean, List<Element>> annotatedMethods = annotatedElements.stream()
31+
.collect(Collectors.partitioningBy(element ->
32+
((ExecutableType) element.asType()).getParameterTypes().size() == 1
33+
&& element.getSimpleName().toString().startsWith("set")));
34+
35+
List<Element> setters = annotatedMethods.get(true);
36+
List<Element> otherMethods = annotatedMethods.get(false);
37+
38+
otherMethods.forEach(element ->
39+
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
40+
"@BuilderProperty must be applied to a setXxx method with a single argument", element));
41+
42+
if (setters.isEmpty()) {
43+
continue;
44+
}
45+
46+
String className = ((TypeElement) setters.get(0).getEnclosingElement()).getQualifiedName().toString();
47+
48+
Map<String, String> setterMap = setters.stream().collect(Collectors.toMap(
49+
setter -> setter.getSimpleName().toString(),
50+
setter -> ((ExecutableType) setter.asType())
51+
.getParameterTypes().get(0).toString()
52+
));
53+
54+
try {
55+
writeBuilderFile(className, setterMap);
56+
} catch (IOException e) {
57+
e.printStackTrace();
58+
}
59+
60+
}
61+
62+
return true;
63+
}
64+
65+
private void writeBuilderFile(String className, Map<String, String> setterMap) throws IOException {
66+
67+
String packageName = null;
68+
int lastDot = className.lastIndexOf('.');
69+
if (lastDot > 0) {
70+
packageName = className.substring(0, lastDot);
71+
}
72+
73+
String simpleClassName = className.substring(lastDot + 1);
74+
String builderClassName = className + "Builder";
75+
String builderSimpleClassName = builderClassName.substring(lastDot + 1);
76+
77+
JavaFileObject builderFile = processingEnv.getFiler().createSourceFile(builderClassName);
78+
try (PrintWriter out = new PrintWriter(builderFile.openWriter())) {
79+
80+
if (packageName != null) {
81+
out.print("package ");
82+
out.print(packageName);
83+
out.println(";");
84+
out.println();
85+
}
86+
87+
out.print("public class ");
88+
out.print(builderSimpleClassName);
89+
out.println(" {");
90+
out.println();
91+
92+
out.print(" private ");
93+
out.print(simpleClassName);
94+
out.print(" object = new ");
95+
out.print(simpleClassName);
96+
out.println("();");
97+
out.println();
98+
99+
out.print(" public ");
100+
out.print(simpleClassName);
101+
out.println(" build() {");
102+
out.println(" return object;");
103+
out.println(" }");
104+
out.println();
105+
106+
setterMap.entrySet().forEach(setter -> {
107+
String methodName = setter.getKey();
108+
String argumentType = setter.getValue();
109+
110+
out.print(" public ");
111+
out.print(builderSimpleClassName);
112+
out.print(" ");
113+
out.print(methodName);
114+
115+
out.print("(");
116+
117+
out.print(argumentType);
118+
out.println(" value) {");
119+
out.print(" object.");
120+
out.print(methodName);
121+
out.println("(value);");
122+
out.println(" return this;");
123+
out.println(" }");
124+
out.println();
125+
});
126+
127+
out.println("}");
128+
129+
}
130+
}
131+
132+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.baeldung.annotation.processor;
2+
3+
import java.lang.annotation.*;
4+
5+
@Target(ElementType.METHOD)
6+
@Retention(RetentionPolicy.SOURCE)
7+
public @interface BuilderProperty {
8+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<artifactId>annotations</artifactId>
9+
<groupId>com.baeldung</groupId>
10+
<version>1.0.0-SNAPSHOT</version>
11+
<relativePath>../</relativePath>
12+
</parent>
13+
14+
<artifactId>annotation-user</artifactId>
15+
16+
<dependencies>
17+
18+
<dependency>
19+
<groupId>com.baeldung</groupId>
20+
<artifactId>annotation-processing</artifactId>
21+
<version>${project.parent.version}</version>
22+
</dependency>
23+
24+
<dependency>
25+
<groupId>junit</groupId>
26+
<artifactId>junit</artifactId>
27+
<version>4.12</version>
28+
<scope>test</scope>
29+
</dependency>
30+
31+
</dependencies>
32+
33+
<build>
34+
35+
<plugins>
36+
37+
<plugin>
38+
<groupId>org.apache.maven.plugins</groupId>
39+
<artifactId>maven-compiler-plugin</artifactId>
40+
<version>3.5.1</version>
41+
<configuration>
42+
<source>1.8</source>
43+
<target>1.8</target>
44+
</configuration>
45+
</plugin>
46+
47+
</plugins>
48+
49+
</build>
50+
51+
</project>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.baeldung.annotation;
2+
3+
import com.baeldung.annotation.processor.BuilderProperty;
4+
5+
public class Person {
6+
7+
private int age;
8+
9+
private String name;
10+
11+
public int getAge() {
12+
return age;
13+
}
14+
15+
@BuilderProperty
16+
public void setAge(int age) {
17+
this.age = age;
18+
}
19+
20+
public String getName() {
21+
return name;
22+
}
23+
24+
@BuilderProperty
25+
public void setName(String name) {
26+
this.name = name;
27+
}
28+
29+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.baeldung.annotation;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertEquals;
6+
7+
public class PersonBuilderTest {
8+
9+
@Test
10+
public void whenBuildPersonWithBuilder_thenObjectHasPropertyValues() {
11+
12+
Person person = new PersonBuilder()
13+
.setAge(25)
14+
.setName("John")
15+
.build();
16+
17+
assertEquals(25, person.getAge());
18+
assertEquals("John", person.getName());
19+
20+
}
21+
22+
}

annotations/pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>parent-modules</artifactId>
7+
<groupId>com.baeldung</groupId>
8+
<version>1.0.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>annotations</artifactId>
13+
<packaging>pom</packaging>
14+
15+
<modules>
16+
<module>annotation-processing</module>
17+
<module>annotation-user</module>
18+
</modules>
19+
20+
</project>

core-java-8/pom.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
22
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
33
<modelVersion>4.0.0</modelVersion>
4+
45
<groupId>com.baeldung</groupId>
6+
<version>1.0.0-SNAPSHOT</version>
57
<artifactId>core-java8</artifactId>
6-
<version>0.1-SNAPSHOT</version>
78

89
<name>core-java8</name>
910

@@ -111,6 +112,9 @@
111112
</build>
112113

113114
<properties>
115+
116+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
117+
114118
<!-- logging -->
115119
<org.slf4j.version>1.7.13</org.slf4j.version>
116120
<logback.version>1.0.13</logback.version>

core-java-8/src/test/resources/.gitignore

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse facilisis neque sed turpis venenatis, non dignissim risus volutpat.

0 commit comments

Comments
 (0)