Lines 45-51
Link Here
|
45 |
import java.io.FileNotFoundException; |
45 |
import java.io.FileNotFoundException; |
46 |
import java.io.IOException; |
46 |
import java.io.IOException; |
47 |
import java.io.InputStream; |
47 |
import java.io.InputStream; |
48 |
import java.io.ObjectOutputStream; |
48 |
import java.lang.annotation.Annotation; |
49 |
import java.net.URI; |
49 |
import java.net.URI; |
50 |
import java.util.Arrays; |
50 |
import java.util.Arrays; |
51 |
import java.util.LinkedHashMap; |
51 |
import java.util.LinkedHashMap; |
Lines 146-153
Link Here
|
146 |
* {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
146 |
* {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
147 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
147 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
148 |
*/ |
148 |
*/ |
149 |
public File instanceFile(String path, String name, Class type) throws IllegalArgumentException, LayerGenerationException { |
149 |
public File instanceFile(String path, String name, Class<?> type) throws IllegalArgumentException, LayerGenerationException { |
150 |
String[] clazzOrMethod = instantiableClassOrMethod(type); |
150 |
return instanceFile(path, name, type, null, null); |
|
|
151 |
} |
152 |
/** |
153 |
* Generates an instance file whose {@code InstanceCookie} would load the associated class or method. |
154 |
* Useful for {@link LayerGeneratingProcessor}s which define layer fragments which instantiate Java objects from the annotated code. |
155 |
* <p>While you can pick a specific instance file name, if possible you should pass null for {@code name} |
156 |
* as using the generated name will help avoid accidental name collisions between annotations. |
157 |
* @param path path to folder of instance file, e.g. {@code "Menu/File"} |
158 |
* @param name instance file basename, e.g. {@code "my-menu-Item"}, or null to pick a name according to the element |
159 |
* @param type a type to which the instance ought to be assignable, or null to skip this check |
160 |
* @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
161 |
* @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
162 |
* @return an instance file (call {@link File#write} to finalize) |
163 |
* @throws IllegalArgumentException if the builder is not associated with exactly one |
164 |
* {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
165 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
166 |
* @since 7.50 |
167 |
*/ |
168 |
public File instanceFile(String path, String name, Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException { |
169 |
String[] clazzOrMethod = instantiableClassOrMethod(type, annotation, annotationMethod); |
151 |
String clazz = clazzOrMethod[0]; |
170 |
String clazz = clazzOrMethod[0]; |
152 |
String method = clazzOrMethod[1]; |
171 |
String method = clazzOrMethod[1]; |
153 |
String basename; |
172 |
String basename; |
Lines 185-191
Link Here
|
185 |
* @since org.openide.filesystems 7.27 |
204 |
* @since org.openide.filesystems 7.27 |
186 |
*/ |
205 |
*/ |
187 |
public File instanceFile(String path, String name) throws IllegalArgumentException, LayerGenerationException { |
206 |
public File instanceFile(String path, String name) throws IllegalArgumentException, LayerGenerationException { |
188 |
String[] clazzOrMethod = instantiableClassOrMethod(null); |
207 |
return instanceFile(path, name, null, null); |
|
|
208 |
} |
209 |
/** |
210 |
* Generates an instance file that is <em>not initialized</em> with an instance. |
211 |
* Useful for {@link LayerGeneratingProcessor}s which define layer fragments |
212 |
* which indirectly instantiate Java objects from the annotated code via a generic factory method. |
213 |
* Invoke the factory using {@link File#methodvalue} on {@code instanceCreate} |
214 |
* and configure it with a {@link File#instanceAttribute} appropriate to the factory. |
215 |
* <p>While you can pick a specific instance file name, if possible you should pass null for {@code name} |
216 |
* as using the generated name will help avoid accidental name collisions between annotations. |
217 |
* @param path path to folder of instance file, e.g. {@code "Menu/File"} |
218 |
* @param name instance file basename, e.g. {@code "my-menu-Item"}, or null to pick a name according to the element |
219 |
* @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
220 |
* @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
221 |
* @return an instance file (call {@link File#write} to finalize) |
222 |
* @throws IllegalArgumentException if the builder is not associated with exactly one |
223 |
* {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
224 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance |
225 |
* @since org.openide.filesystems 7.50 |
226 |
*/ |
227 |
public File instanceFile(String path, String name, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException { |
228 |
String[] clazzOrMethod = instantiableClassOrMethod(null, annotation, annotationMethod); |
189 |
String clazz = clazzOrMethod[0]; |
229 |
String clazz = clazzOrMethod[0]; |
190 |
String method = clazzOrMethod[1]; |
230 |
String method = clazzOrMethod[1]; |
191 |
String basename; |
231 |
String basename; |
Lines 200-206
Link Here
|
200 |
return file(path + "/" + basename + ".instance"); |
240 |
return file(path + "/" + basename + ".instance"); |
201 |
} |
241 |
} |
202 |
|
242 |
|
203 |
private String[] instantiableClassOrMethod(Class type) throws IllegalArgumentException, LayerGenerationException { |
243 |
private String[] instantiableClassOrMethod(Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException { |
204 |
if (originatingElement == null) { |
244 |
if (originatingElement == null) { |
205 |
throw new IllegalArgumentException("Only applicable to builders with exactly one associated element"); |
245 |
throw new IllegalArgumentException("Only applicable to builders with exactly one associated element"); |
206 |
} |
246 |
} |
Lines 212-218
Link Here
|
212 |
case CLASS: { |
252 |
case CLASS: { |
213 |
String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement).toString(); |
253 |
String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement).toString(); |
214 |
if (originatingElement.getModifiers().contains(Modifier.ABSTRACT)) { |
254 |
if (originatingElement.getModifiers().contains(Modifier.ABSTRACT)) { |
215 |
throw new LayerGenerationException(clazz + " must not be abstract", originatingElement); |
255 |
throw new LayerGenerationException(clazz + " must not be abstract", originatingElement, processingEnv, annotation, annotationMethod); |
216 |
} |
256 |
} |
217 |
{ |
257 |
{ |
218 |
boolean hasDefaultCtor = false; |
258 |
boolean hasDefaultCtor = false; |
Lines 223-236
Link Here
|
223 |
} |
263 |
} |
224 |
} |
264 |
} |
225 |
if (!hasDefaultCtor) { |
265 |
if (!hasDefaultCtor) { |
226 |
throw new LayerGenerationException(clazz + " must have a no-argument constructor", originatingElement); |
266 |
throw new LayerGenerationException(clazz + " must have a no-argument constructor", originatingElement, processingEnv, annotation, annotationMethod); |
227 |
} |
267 |
} |
228 |
} |
268 |
} |
229 |
if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(originatingElement.asType(), typeMirror)) { |
269 |
if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(originatingElement.asType(), typeMirror)) { |
230 |
throw new LayerGenerationException(clazz + " is not assignable to " + typeMirror, originatingElement); |
270 |
throw new LayerGenerationException(clazz + " is not assignable to " + typeMirror, originatingElement, processingEnv, annotation, annotationMethod); |
231 |
} |
271 |
} |
232 |
if (!originatingElement.getModifiers().contains(Modifier.PUBLIC)) { |
272 |
if (!originatingElement.getModifiers().contains(Modifier.PUBLIC)) { |
233 |
throw new LayerGenerationException(clazz + " is not public", originatingElement); |
273 |
throw new LayerGenerationException(clazz + " is not public", originatingElement, processingEnv, annotation, annotationMethod); |
234 |
} |
274 |
} |
235 |
return new String[] {clazz, null}; |
275 |
return new String[] {clazz, null}; |
236 |
} |
276 |
} |
Lines 238-250
Link Here
|
238 |
String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement.getEnclosingElement()).toString(); |
278 |
String clazz = processingEnv.getElementUtils().getBinaryName((TypeElement) originatingElement.getEnclosingElement()).toString(); |
239 |
String method = originatingElement.getSimpleName().toString(); |
279 |
String method = originatingElement.getSimpleName().toString(); |
240 |
if (!originatingElement.getModifiers().contains(Modifier.STATIC)) { |
280 |
if (!originatingElement.getModifiers().contains(Modifier.STATIC)) { |
241 |
throw new LayerGenerationException(clazz + "." + method + " must be static", originatingElement); |
281 |
throw new LayerGenerationException(clazz + "." + method + " must be static", originatingElement, processingEnv, annotation, annotationMethod); |
242 |
} |
282 |
} |
243 |
if (!((ExecutableElement) originatingElement).getParameters().isEmpty()) { |
283 |
if (!((ExecutableElement) originatingElement).getParameters().isEmpty()) { |
244 |
throw new LayerGenerationException(clazz + "." + method + " must not take arguments", originatingElement); |
284 |
throw new LayerGenerationException(clazz + "." + method + " must not take arguments", originatingElement, processingEnv, annotation, annotationMethod); |
245 |
} |
285 |
} |
246 |
if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement) originatingElement).getReturnType(), typeMirror)) { |
286 |
if (typeMirror != null && !processingEnv.getTypeUtils().isAssignable(((ExecutableElement) originatingElement).getReturnType(), typeMirror)) { |
247 |
throw new LayerGenerationException(clazz + "." + method + " is not assignable to " + typeMirror, originatingElement); |
287 |
throw new LayerGenerationException(clazz + "." + method + " is not assignable to " + typeMirror, originatingElement, processingEnv, annotation, annotationMethod); |
248 |
} |
288 |
} |
249 |
return new String[] {clazz, method}; |
289 |
return new String[] {clazz, method}; |
250 |
} |
290 |
} |
Lines 485-492
Link Here
|
485 |
* @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
525 |
* @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
486 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
526 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
487 |
*/ |
527 |
*/ |
488 |
public File instanceAttribute(String attr, Class type) throws IllegalArgumentException, LayerGenerationException { |
528 |
public File instanceAttribute(String attr, Class<?> type) throws IllegalArgumentException, LayerGenerationException { |
489 |
String[] clazzOrMethod = instantiableClassOrMethod(type); |
529 |
return instanceAttribute(attr, type, null, null); |
|
|
530 |
} |
531 |
/** |
532 |
* Adds an attribute to load the associated class or method. |
533 |
* Useful for {@link LayerGeneratingProcessor}s which define layer fragments which instantiate Java objects from the annotated code. |
534 |
* @param attr the attribute name |
535 |
* @param type a type to which the instance ought to be assignable, or null to skip this check |
536 |
* @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
537 |
* @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
538 |
* @return this builder |
539 |
* @throws IllegalArgumentException if the associated element is not a {@linkplain TypeElement class} or {@linkplain ExecutableElement method} |
540 |
* @throws LayerGenerationException if the associated element would not be loadable as an instance of the specified type |
541 |
* @since 7.50 |
542 |
*/ |
543 |
public File instanceAttribute(String attr, Class<?> type, Annotation annotation, String annotationMethod) throws IllegalArgumentException, LayerGenerationException { |
544 |
String[] clazzOrMethod = instantiableClassOrMethod(type, annotation, annotationMethod); |
490 |
if (clazzOrMethod[1] == null) { |
545 |
if (clazzOrMethod[1] == null) { |
491 |
newvalue(attr, clazzOrMethod[0]); |
546 |
newvalue(attr, clazzOrMethod[0]); |
492 |
} else { |
547 |
} else { |
Lines 518-523
Link Here
|
518 |
* @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources |
573 |
* @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources |
519 |
*/ |
574 |
*/ |
520 |
public File bundlevalue(String attr, String label) throws LayerGenerationException { |
575 |
public File bundlevalue(String attr, String label) throws LayerGenerationException { |
|
|
576 |
return bundlevalue(attr, label, null, null); |
577 |
} |
578 |
/** |
579 |
* Adds an attribute for a possibly localized string. |
580 |
* @param attr the attribute name |
581 |
* @param label either a general string to store as is, or a resource bundle reference |
582 |
* such as {@code "my.module.Bundle#some_key"}, |
583 |
* or just {@code "#some_key"} to load from a {@code "Bundle"} |
584 |
* in the same package as the element associated with this builder (if exactly one) |
585 |
* @param annotation as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
586 |
* @param annotationMethod as in {@link LayerGenerationException#LayerGenerationException(String,Element,ProcessingEnvironment,Annotation,String)} |
587 |
* @return this builder |
588 |
* @throws LayerGenerationException if a bundle key is requested but it cannot be found in sources |
589 |
* @since 7.50 |
590 |
*/ |
591 |
public File bundlevalue(String attr, String label, Annotation annotation, String annotationMethod) throws LayerGenerationException { |
521 |
String javaIdentifier = "(?:\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)"; |
592 |
String javaIdentifier = "(?:\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*)"; |
522 |
Matcher m = Pattern.compile("((?:" + javaIdentifier + "\\.)+[^\\s.#]+)?#(\\S*)").matcher(label); |
593 |
Matcher m = Pattern.compile("((?:" + javaIdentifier + "\\.)+[^\\s.#]+)?#(\\S*)").matcher(label); |
523 |
if (m.matches()) { |
594 |
if (m.matches()) { |
Lines 533-546
Link Here
|
533 |
} |
604 |
} |
534 |
bundle = ((PackageElement) referenceElement).getQualifiedName() + ".Bundle"; |
605 |
bundle = ((PackageElement) referenceElement).getQualifiedName() + ".Bundle"; |
535 |
} |
606 |
} |
536 |
verifyBundleKey(bundle, key, m.group(1) == null); |
607 |
verifyBundleKey(bundle, key, m.group(1) == null, annotation, annotationMethod); |
537 |
bundlevalue(attr, bundle, key); |
608 |
bundlevalue(attr, bundle, key); |
538 |
} else { |
609 |
} else { |
539 |
stringvalue(attr, label); |
610 |
stringvalue(attr, label); |
540 |
} |
611 |
} |
541 |
return this; |
612 |
return this; |
542 |
} |
613 |
} |
543 |
private void verifyBundleKey(String bundle, String key, boolean samePackage) throws LayerGenerationException { |
614 |
private void verifyBundleKey(String bundle, String key, boolean samePackage, Annotation annotation, String annotationMethod) throws LayerGenerationException { |
544 |
if (processingEnv == null) { |
615 |
if (processingEnv == null) { |
545 |
return; |
616 |
return; |
546 |
} |
617 |
} |
Lines 572-584
Link Here
|
572 |
Properties p = new Properties(); |
643 |
Properties p = new Properties(); |
573 |
p.load(is); |
644 |
p.load(is); |
574 |
if (p.getProperty(key) == null) { |
645 |
if (p.getProperty(key) == null) { |
575 |
throw new LayerGenerationException("No key '" + key + "' found in " + resource, originatingElement); |
646 |
throw new LayerGenerationException("No key '" + key + "' found in " + resource, originatingElement, processingEnv, annotation, annotationMethod); |
576 |
} |
647 |
} |
577 |
} finally { |
648 |
} finally { |
578 |
is.close(); |
649 |
is.close(); |
579 |
} |
650 |
} |
580 |
} catch (IOException x) { |
651 |
} catch (IOException x) { |
581 |
throw new LayerGenerationException("Could not open " + resource + ": " + x, originatingElement); |
652 |
throw new LayerGenerationException("Could not open " + resource + ": " + x, originatingElement, processingEnv, annotation, annotationMethod); |
582 |
} |
653 |
} |
583 |
} |
654 |
} |
584 |
|
655 |
|