1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.sw4j.tool.annotation.jpa.processor;
18
19 import java.io.File;
20 import java.io.FileInputStream;
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Iterator;
24 import java.util.Map;
25 import java.util.Properties;
26 import java.util.ServiceLoader;
27 import java.util.Set;
28 import javax.annotation.Nonnull;
29 import javax.annotation.Nullable;
30 import javax.annotation.processing.AbstractProcessor;
31 import javax.annotation.processing.ProcessingEnvironment;
32 import javax.annotation.processing.RoundEnvironment;
33 import javax.annotation.processing.SupportedAnnotationTypes;
34 import javax.annotation.processing.SupportedOptions;
35 import javax.annotation.processing.SupportedSourceVersion;
36 import javax.lang.model.SourceVersion;
37 import javax.lang.model.element.TypeElement;
38 import javax.persistence.Entity;
39 import javax.tools.Diagnostic;
40 import org.sw4j.tool.annotation.jpa.generator.GeneratorService;
41 import org.sw4j.tool.annotation.jpa.generator.model.Model;
42
43
44
45
46
47
48 @SupportedAnnotationTypes("javax.persistence.Entity")
49 @SupportedSourceVersion(SourceVersion.RELEASE_7)
50 @SupportedOptions(AnnotationProcessor.PROPERTIES_OPTION)
51 public class AnnotationProcessor extends AbstractProcessor {
52
53
54 public static final String PROPERTIES_OPTION = "tool.jpa.properties";
55
56
57 private final Model model;
58
59
60 private final EntityProcessor entityProcessor;
61
62 private boolean firstRound = true;
63
64
65
66
67 public AnnotationProcessor() {
68 this.model = new Model();
69 this.entityProcessor = new EntityProcessor();
70 }
71
72
73
74
75
76
77
78
79 @Override
80 public void init(@Nonnull final ProcessingEnvironment processingEnv) {
81 super.init(processingEnv);
82 this.entityProcessor.init(this.processingEnv);
83 }
84
85
86
87
88
89
90
91
92 @Override
93 public boolean process(@Nonnull final Set<? extends TypeElement> annotations,
94 @Nonnull final RoundEnvironment roundEnv) {
95 if (firstRound) {
96 this.processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Running JPA annotation processor");
97 firstRound = false;
98 }
99 String propertiesOption = this.processingEnv.getOptions().get(PROPERTIES_OPTION);
100 Map<String, Properties> properties = readProperties(propertiesOption);
101 this.entityProcessor.process(roundEnv.getElementsAnnotatedWith(Entity.class), model);
102
103 if (roundEnv.processingOver()) {
104 ServiceLoader<GeneratorService> generatorServiceLoader = setupGenerators(properties);
105 Iterator<GeneratorService> generators = generatorServiceLoader.iterator();
106 while (generators.hasNext()) {
107 GeneratorService generator = generators.next();
108 if (generator.canProcess()) {
109 try {
110 generator.process(this.model, this.processingEnv);
111 } catch (IOException ioex) {
112 this.processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
113 ioex.toString());
114 }
115 }
116 }
117 }
118
119 return false;
120 }
121
122
123
124
125
126
127
128 @Nonnull
129 private Map<String, Properties> readProperties(@Nullable final String fileName) {
130 Map<String, Properties> result = new HashMap<>();
131 if (fileName != null) {
132 File propertiesFile = new File(fileName);
133 if (propertiesFile.exists()) {
134 Properties allProperties = new Properties();
135 try (FileInputStream fis = new FileInputStream(propertiesFile)) {
136 allProperties.load(fis);
137 } catch (IOException ioex) {
138 this.processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
139 new StringBuilder("Cannot access the file \"").append(fileName)
140 .append("\". Ignoring Properties.\nError: ").append(ioex.getMessage()));
141 }
142 if (!allProperties.isEmpty()) {
143 for (String propertyName: allProperties.stringPropertyNames()) {
144 int dotPos = propertyName.indexOf('.');
145 if (dotPos >= 0) {
146 String prefix = propertyName.substring(0, dotPos);
147 String suffix = propertyName.substring(dotPos + 1);
148 Properties prefixedProperties = result.get(prefix);
149 if (prefixedProperties == null) {
150 prefixedProperties = new Properties();
151 result.put(prefix, prefixedProperties);
152 }
153 prefixedProperties.setProperty(suffix, allProperties.getProperty(propertyName));
154 }
155 }
156 }
157 }
158 }
159 return result;
160 }
161
162
163
164
165
166
167
168 @Nonnull
169 private ServiceLoader<GeneratorService> setupGenerators(@Nonnull final Map<String, Properties> properties) {
170 ServiceLoader<GeneratorService> generatorServiceLoader = ServiceLoader.load(GeneratorService.class,
171 this.getClass().getClassLoader());
172 Iterator<GeneratorService> generators = generatorServiceLoader.iterator();
173 while (generators.hasNext()) {
174 GeneratorService generator = generators.next();
175 if (properties.containsKey(generator.getPrefix())) {
176 generator.setProperties(properties.get(generator.getPrefix()));
177 }
178 }
179 return generatorServiceLoader;
180 }
181
182 }