jtulach@0
|
1 |
/**
|
jaroslav@358
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
jtulach@0
|
3 |
*
|
jaroslav@358
|
4 |
* Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
|
jtulach@0
|
5 |
*
|
jaroslav@358
|
6 |
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
|
jaroslav@358
|
7 |
* Other names may be trademarks of their respective owners.
|
jtulach@0
|
8 |
*
|
jaroslav@358
|
9 |
* The contents of this file are subject to the terms of either the GNU
|
jaroslav@358
|
10 |
* General Public License Version 2 only ("GPL") or the Common
|
jaroslav@358
|
11 |
* Development and Distribution License("CDDL") (collectively, the
|
jaroslav@358
|
12 |
* "License"). You may not use this file except in compliance with the
|
jaroslav@358
|
13 |
* License. You can obtain a copy of the License at
|
jaroslav@358
|
14 |
* http://www.netbeans.org/cddl-gplv2.html
|
jaroslav@358
|
15 |
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
|
jaroslav@358
|
16 |
* specific language governing permissions and limitations under the
|
jaroslav@358
|
17 |
* License. When distributing the software, include this License Header
|
jaroslav@358
|
18 |
* Notice in each file and include the License file at
|
jaroslav@358
|
19 |
* nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
|
jaroslav@358
|
20 |
* particular file as subject to the "Classpath" exception as provided
|
jaroslav@358
|
21 |
* by Oracle in the GPL Version 2 section of the License file that
|
jaroslav@358
|
22 |
* accompanied this code. If applicable, add the following below the
|
jaroslav@358
|
23 |
* License Header, with the fields enclosed by brackets [] replaced by
|
jaroslav@358
|
24 |
* your own identifying information:
|
jaroslav@358
|
25 |
* "Portions Copyrighted [year] [name of copyright owner]"
|
jaroslav@358
|
26 |
*
|
jaroslav@358
|
27 |
* Contributor(s):
|
jaroslav@358
|
28 |
*
|
jaroslav@358
|
29 |
* The Original Software is NetBeans. The Initial Developer of the Original
|
jaroslav@358
|
30 |
* Software is Oracle. Portions Copyright 2013-2013 Oracle. All Rights Reserved.
|
jaroslav@358
|
31 |
*
|
jaroslav@358
|
32 |
* If you wish your version of this file to be governed by only the CDDL
|
jaroslav@358
|
33 |
* or only the GPL Version 2, indicate your decision by adding
|
jaroslav@358
|
34 |
* "[Contributor] elects to include this software in this distribution
|
jaroslav@358
|
35 |
* under the [CDDL or GPL Version 2] license." If you do not indicate a
|
jaroslav@358
|
36 |
* single choice of license, a recipient has the option to distribute
|
jaroslav@358
|
37 |
* your version of this file under either the CDDL, the GPL Version 2 or
|
jaroslav@358
|
38 |
* to extend the choice of license to its licensees as provided above.
|
jaroslav@358
|
39 |
* However, if you add GPL Version 2 code and therefore, elected the GPL
|
jaroslav@358
|
40 |
* Version 2 license, then the option applies only if the new code is
|
jaroslav@358
|
41 |
* made subject to such option by the copyright holder.
|
jtulach@0
|
42 |
*/
|
jaroslav@362
|
43 |
package org.netbeans.html.geo.impl;
|
jtulach@0
|
44 |
|
jtulach@0
|
45 |
import java.io.IOException;
|
jtulach@0
|
46 |
import java.io.Writer;
|
jaroslav@212
|
47 |
import java.util.List;
|
jaroslav@172
|
48 |
import java.util.Locale;
|
jtulach@0
|
49 |
import java.util.Set;
|
jaroslav@71
|
50 |
import java.util.logging.Level;
|
jaroslav@70
|
51 |
import java.util.logging.Logger;
|
jtulach@0
|
52 |
import javax.annotation.processing.AbstractProcessor;
|
jtulach@0
|
53 |
import javax.annotation.processing.Processor;
|
jtulach@0
|
54 |
import javax.annotation.processing.RoundEnvironment;
|
jtulach@0
|
55 |
import javax.annotation.processing.SupportedAnnotationTypes;
|
jaroslav@58
|
56 |
import javax.annotation.processing.SupportedSourceVersion;
|
jaroslav@58
|
57 |
import javax.lang.model.SourceVersion;
|
jtulach@0
|
58 |
import javax.lang.model.element.Element;
|
jtulach@0
|
59 |
import javax.lang.model.element.ElementKind;
|
jtulach@0
|
60 |
import javax.lang.model.element.ExecutableElement;
|
jtulach@0
|
61 |
import javax.lang.model.element.Modifier;
|
jtulach@0
|
62 |
import javax.lang.model.element.PackageElement;
|
jtulach@0
|
63 |
import javax.lang.model.element.TypeElement;
|
jaroslav@212
|
64 |
import javax.lang.model.element.VariableElement;
|
jaroslav@176
|
65 |
import javax.lang.model.type.TypeMirror;
|
jtulach@0
|
66 |
import javax.tools.Diagnostic;
|
jaroslav@172
|
67 |
import javax.tools.JavaFileObject;
|
jaroslav@172
|
68 |
import net.java.html.geo.OnLocation;
|
jaroslav@176
|
69 |
import net.java.html.geo.Position;
|
jtulach@0
|
70 |
import org.openide.util.lookup.ServiceProvider;
|
jtulach@0
|
71 |
|
jaroslav@172
|
72 |
/** Annotation processor to generate callbacks from {@link GeoHandle} class.
|
jtulach@0
|
73 |
*
|
jtulach@0
|
74 |
* @author Jaroslav Tulach <jtulach@netbeans.org>
|
jtulach@0
|
75 |
*/
|
jtulach@0
|
76 |
@ServiceProvider(service=Processor.class)
|
jaroslav@100
|
77 |
@SupportedSourceVersion(SourceVersion.RELEASE_6)
|
jtulach@0
|
78 |
@SupportedAnnotationTypes({
|
jaroslav@172
|
79 |
"net.java.html.geo.OnLocation"
|
jtulach@0
|
80 |
})
|
jaroslav@172
|
81 |
public final class GeoProcessor extends AbstractProcessor {
|
jaroslav@172
|
82 |
private static final Logger LOG = Logger.getLogger(GeoProcessor.class.getName());
|
jtulach@0
|
83 |
@Override
|
jtulach@0
|
84 |
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
|
jtulach@0
|
85 |
boolean ok = true;
|
jaroslav@172
|
86 |
for (Element e : roundEnv.getElementsAnnotatedWith(OnLocation.class)) {
|
jaroslav@172
|
87 |
if (!processLocation(e)) {
|
jtulach@0
|
88 |
ok = false;
|
jtulach@0
|
89 |
}
|
jtulach@0
|
90 |
}
|
jtulach@0
|
91 |
return ok;
|
jtulach@0
|
92 |
}
|
jtulach@0
|
93 |
|
jtulach@0
|
94 |
private void error(String msg, Element e) {
|
jtulach@0
|
95 |
processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
|
jtulach@0
|
96 |
}
|
jtulach@0
|
97 |
|
jaroslav@172
|
98 |
private boolean processLocation(Element e) {
|
jaroslav@172
|
99 |
if (e.getKind() != ElementKind.METHOD) {
|
jaroslav@172
|
100 |
return false;
|
jaroslav@172
|
101 |
}
|
jaroslav@172
|
102 |
ExecutableElement me = (ExecutableElement) e;
|
jaroslav@172
|
103 |
OnLocation ol = e.getAnnotation(OnLocation.class);
|
jaroslav@172
|
104 |
if (ol == null) {
|
jtulach@0
|
105 |
return true;
|
jtulach@0
|
106 |
}
|
jaroslav@176
|
107 |
if (me.getModifiers().contains(Modifier.PRIVATE)) {
|
jaroslav@176
|
108 |
error("Method annotated by @OnLocation cannot be private", e);
|
jaroslav@176
|
109 |
return false;
|
jaroslav@176
|
110 |
}
|
jaroslav@176
|
111 |
TypeMirror positionClass = processingEnv.getElementUtils().getTypeElement(Position.class.getName()).asType();
|
jaroslav@212
|
112 |
final List<? extends VariableElement> params = me.getParameters();
|
jaroslav@212
|
113 |
if (params.size() < 1 || !params.get(0).asType().equals(positionClass)) {
|
jaroslav@212
|
114 |
error("Method annotated by @OnLocation first argument must be net.java.html.geo.Position!", e);
|
jaroslav@176
|
115 |
return false;
|
jaroslav@176
|
116 |
}
|
jaroslav@172
|
117 |
String className = ol.className();
|
jaroslav@172
|
118 |
if (className.isEmpty()) {
|
jaroslav@172
|
119 |
String n = e.getSimpleName().toString();
|
jaroslav@172
|
120 |
if (n.isEmpty()) {
|
jaroslav@172
|
121 |
error("Empty method name", e);
|
jaroslav@172
|
122 |
return false;
|
jaroslav@172
|
123 |
}
|
jaroslav@172
|
124 |
final String firstLetter = n.substring(0, 1).toUpperCase(Locale.ENGLISH);
|
jaroslav@172
|
125 |
className = firstLetter + n.substring(1) + "Handle";
|
jaroslav@172
|
126 |
}
|
jaroslav@172
|
127 |
TypeElement te = (TypeElement)e.getEnclosingElement();
|
jaroslav@172
|
128 |
PackageElement pe = (PackageElement) te.getEnclosingElement();
|
jaroslav@172
|
129 |
final String pkg = pe.getQualifiedName().toString();
|
jaroslav@172
|
130 |
final String fqn = pkg + "." + className;
|
jaroslav@172
|
131 |
final boolean isStatic = me.getModifiers().contains(Modifier.STATIC);
|
jaroslav@212
|
132 |
String sep;
|
jtulach@0
|
133 |
try {
|
jaroslav@172
|
134 |
JavaFileObject fo = processingEnv.getFiler().createSourceFile(fqn, e);
|
jaroslav@172
|
135 |
Writer w = fo.openWriter();
|
jaroslav@172
|
136 |
w.append("package ").append(pkg).append(";\n");
|
jaroslav@175
|
137 |
w.append("class ").append(className).append(" extends net.java.html.geo.Position.Handle {\n");
|
jaroslav@212
|
138 |
if (!isStatic) {
|
jaroslav@212
|
139 |
w.append(" private final ").append(te.getSimpleName()).append(" $i;\n");
|
jaroslav@212
|
140 |
}
|
jaroslav@212
|
141 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
142 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
143 |
w.append(" private final ").append(p.asType().toString()).append(" ").append(p.getSimpleName()).append(";\n");
|
jaroslav@212
|
144 |
}
|
jaroslav@172
|
145 |
w.append(" private ").append(className).append("(boolean oneTime");
|
jaroslav@172
|
146 |
w.append(", ").append(te.getSimpleName()).append(" i");
|
jaroslav@212
|
147 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
148 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
149 |
w.append(", ").append(p.asType().toString()).append(" ").append(p.getSimpleName());
|
jaroslav@212
|
150 |
}
|
jaroslav@172
|
151 |
w.append(") {\n super(oneTime);\n");
|
jaroslav@172
|
152 |
if (!isStatic) {
|
jaroslav@212
|
153 |
w.append(" this.$i = i;\n");
|
jaroslav@212
|
154 |
}
|
jaroslav@212
|
155 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
156 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
157 |
w.append(" this.").append(p.getSimpleName()).append(" = ").append(p.getSimpleName()).append(";\n");
|
jtulach@0
|
158 |
}
|
jaroslav@172
|
159 |
w.append("}\n");
|
jaroslav@175
|
160 |
w.append(" static net.java.html.geo.Position.Handle createQuery(");
|
jaroslav@172
|
161 |
String inst;
|
jaroslav@172
|
162 |
if (!isStatic) {
|
jaroslav@172
|
163 |
w.append(te.getSimpleName()).append(" instance");
|
jaroslav@172
|
164 |
inst = "instance";
|
jaroslav@212
|
165 |
sep = ", ";
|
jaroslav@172
|
166 |
} else {
|
jaroslav@172
|
167 |
inst = "null";
|
jaroslav@212
|
168 |
sep = "";
|
jtulach@0
|
169 |
}
|
jaroslav@212
|
170 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
171 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
172 |
w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
|
jaroslav@212
|
173 |
sep = ", ";
|
jaroslav@212
|
174 |
}
|
jaroslav@212
|
175 |
w.append(") { return new ").append(className).append("(true, ").append(inst);
|
jaroslav@212
|
176 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
177 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
178 |
w.append(", ").append(p.getSimpleName());
|
jaroslav@212
|
179 |
}
|
jaroslav@212
|
180 |
w.append("); }\n");
|
jaroslav@175
|
181 |
w.append(" static net.java.html.geo.Position.Handle createWatch(");
|
jaroslav@172
|
182 |
if (!isStatic) {
|
jaroslav@172
|
183 |
w.append(te.getSimpleName()).append(" instance");
|
jaroslav@212
|
184 |
sep = ", ";
|
jaroslav@212
|
185 |
} else {
|
jaroslav@212
|
186 |
sep = "";
|
jtulach@0
|
187 |
}
|
jaroslav@212
|
188 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
189 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
190 |
w.append(sep).append(p.asType().toString()).append(" ").append(p.getSimpleName());
|
jaroslav@212
|
191 |
}
|
jaroslav@212
|
192 |
w.append(") { return new ").append(className).append("(false, ").append(inst);
|
jaroslav@212
|
193 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
194 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
195 |
w.append(", ").append(p.getSimpleName());
|
jaroslav@212
|
196 |
}
|
jaroslav@212
|
197 |
w.append("); }\n");
|
jaroslav@180
|
198 |
w.append(" @Override protected void onError(Exception t) throws Throwable {\n");
|
jaroslav@174
|
199 |
if (ol.onError().isEmpty()) {
|
jaroslav@174
|
200 |
w.append(" t.printStackTrace();");
|
jaroslav@174
|
201 |
} else {
|
jaroslav@177
|
202 |
if (!findOnError(me, te, ol.onError(), isStatic)) {
|
jaroslav@177
|
203 |
return false;
|
jaroslav@177
|
204 |
}
|
jaroslav@174
|
205 |
if (isStatic) {
|
jaroslav@174
|
206 |
w.append(" ").append(te.getSimpleName()).append(".");
|
jaroslav@174
|
207 |
} else {
|
jaroslav@212
|
208 |
w.append(" $i.");
|
jaroslav@174
|
209 |
}
|
jaroslav@212
|
210 |
w.append(ol.onError()).append("(t");
|
jaroslav@212
|
211 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
212 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
213 |
w.append(", ").append(p.getSimpleName());
|
jaroslav@212
|
214 |
}
|
jaroslav@212
|
215 |
w.append(");\n");
|
jaroslav@174
|
216 |
}
|
jaroslav@174
|
217 |
w.append(" }\n");
|
jaroslav@180
|
218 |
w.append(" @Override protected void onLocation(net.java.html.geo.Position p) throws Throwable {\n");
|
jaroslav@173
|
219 |
if (isStatic) {
|
jaroslav@173
|
220 |
w.append(" ").append(te.getSimpleName()).append(".");
|
jaroslav@173
|
221 |
} else {
|
jaroslav@212
|
222 |
w.append(" $i.");
|
jaroslav@173
|
223 |
}
|
jaroslav@212
|
224 |
w.append(me.getSimpleName()).append("(p");
|
jaroslav@212
|
225 |
for (int i = 1; i < params.size(); i++) {
|
jaroslav@212
|
226 |
final VariableElement p = params.get(i);
|
jaroslav@212
|
227 |
w.append(", ").append(p.getSimpleName());
|
jaroslav@212
|
228 |
}
|
jaroslav@212
|
229 |
w.append(");\n");
|
jaroslav@173
|
230 |
w.append(" }\n");
|
jaroslav@172
|
231 |
w.append("}\n");
|
jaroslav@172
|
232 |
w.close();
|
jtulach@0
|
233 |
} catch (IOException ex) {
|
jaroslav@172
|
234 |
Logger.getLogger(GeoProcessor.class.getName()).log(Level.SEVERE, null, ex);
|
jaroslav@172
|
235 |
error("Can't write handler class: " + ex.getMessage(), e);
|
jtulach@0
|
236 |
return false;
|
jtulach@0
|
237 |
}
|
jtulach@0
|
238 |
|
jtulach@0
|
239 |
return true;
|
jtulach@0
|
240 |
}
|
jaroslav@177
|
241 |
|
jaroslav@212
|
242 |
private boolean findOnError(ExecutableElement errElem, TypeElement te, String name, boolean onlyStatic) {
|
jaroslav@177
|
243 |
String err = null;
|
jaroslav@212
|
244 |
METHODS: for (Element e : te.getEnclosedElements()) {
|
jaroslav@177
|
245 |
if (e.getKind() != ElementKind.METHOD) {
|
jaroslav@177
|
246 |
continue;
|
jaroslav@177
|
247 |
}
|
jaroslav@177
|
248 |
if (!e.getSimpleName().contentEquals(name)) {
|
jaroslav@177
|
249 |
continue;
|
jaroslav@177
|
250 |
}
|
jaroslav@177
|
251 |
if (onlyStatic && !e.getModifiers().contains(Modifier.STATIC)) {
|
jaroslav@212
|
252 |
errElem = (ExecutableElement) e;
|
jaroslav@177
|
253 |
err = "Would have to be static";
|
jaroslav@177
|
254 |
continue;
|
jaroslav@177
|
255 |
}
|
jaroslav@177
|
256 |
ExecutableElement ee = (ExecutableElement) e;
|
jaroslav@177
|
257 |
TypeMirror excType = processingEnv.getElementUtils().getTypeElement(Exception.class.getName()).asType();
|
jaroslav@212
|
258 |
final List<? extends VariableElement> params = ee.getParameters();
|
jaroslav@212
|
259 |
if (params.size() < 1 ||
|
jaroslav@177
|
260 |
!processingEnv.getTypeUtils().isAssignable(excType, ee.getParameters().get(0).asType())
|
jaroslav@177
|
261 |
) {
|
jaroslav@212
|
262 |
errElem = (ExecutableElement) e;
|
jaroslav@212
|
263 |
err = "Error method first argument needs to be Exception";
|
jaroslav@177
|
264 |
continue;
|
jaroslav@177
|
265 |
}
|
jaroslav@212
|
266 |
final List<? extends Element> origParams = errElem.getParameters();
|
jaroslav@212
|
267 |
if (params.size() != origParams.size()) {
|
jaroslav@212
|
268 |
errElem = (ExecutableElement) e;
|
jaroslav@212
|
269 |
err = "Error method must have the same parameters as @OnLocation one";
|
jaroslav@212
|
270 |
continue;
|
jaroslav@212
|
271 |
}
|
jaroslav@212
|
272 |
for (int i = 1; i < origParams.size(); i++) {
|
jaroslav@212
|
273 |
final TypeMirror t1 = params.get(i).asType();
|
jaroslav@212
|
274 |
final TypeMirror t2 = origParams.get(i).asType();
|
jaroslav@212
|
275 |
if (!processingEnv.getTypeUtils().isSameType(t1, t2)) {
|
jaroslav@212
|
276 |
errElem = (ExecutableElement) e;
|
jaroslav@212
|
277 |
err = "Error method must have the same parameters as @OnLocation one";
|
jaroslav@212
|
278 |
continue METHODS;
|
jaroslav@212
|
279 |
}
|
jaroslav@212
|
280 |
}
|
jaroslav@177
|
281 |
return true;
|
jaroslav@177
|
282 |
}
|
jaroslav@177
|
283 |
if (err == null) {
|
jaroslav@177
|
284 |
err = "Cannot find " + name + "(Exception) method in this class";
|
jaroslav@177
|
285 |
}
|
jaroslav@177
|
286 |
error(err, errElem);
|
jaroslav@177
|
287 |
return false;
|
jaroslav@177
|
288 |
}
|
jtulach@0
|
289 |
}
|