1 /*
2  * Copyright (c) 2002-2008 LWJGL Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'LWJGL' nor the names of
17  *   its contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.lwjgl.util.generator;
33 
34 /**
35  *
36  * Various utility methods to the generator.
37  *
38  * @author elias_naur <elias_naur@users.sourceforge.net>
39  * @version $Revision$ $Id$
40  */
41 import org.lwjgl.PointerBuffer;
42 import org.lwjgl.PointerWrapper;
43 import org.lwjgl.util.generator.opengl.GLboolean;
44 import org.lwjgl.util.generator.opengl.GLchar;
45 import org.lwjgl.util.generator.opengl.GLcharARB;
46 import org.lwjgl.util.generator.opengl.GLreturn;
47 
48 import java.io.PrintWriter;
49 import java.nio.Buffer;
50 import java.nio.ByteBuffer;
51 import java.util.*;
52 import java.util.regex.Pattern;
53 import javax.annotation.processing.ProcessingEnvironment;
54 import javax.lang.model.element.*;
55 import javax.lang.model.type.TypeKind;
56 import javax.lang.model.type.TypeMirror;
57 import javax.lang.model.type.TypeVisitor;
58 import javax.lang.model.util.ElementFilter;
59 
60 public class Utils {
61 
62 	public static final  String TYPEDEF_POSTFIX                 = "PROC";
63 	public static final  String FUNCTION_POINTER_VAR_NAME       = "function_pointer";
64 	public static final  String FUNCTION_POINTER_POSTFIX        = "_pointer";
65 	public static final  String CHECKS_CLASS_NAME               = "GLChecks";
66 	public static final  String CONTEXT_CAPS_CLASS_NAME         = "ContextCapabilities";
67 	public static final  String STUB_INITIALIZER_NAME           = "initNativeStubs";
68 	public static final  String BUFFER_OBJECT_METHOD_POSTFIX    = "BO";
69 	public static final  String BUFFER_OBJECT_PARAMETER_POSTFIX = "_buffer_offset";
70 	public static final  String RESULT_SIZE_NAME                = "result_size";
71 	public static final  String RESULT_VAR_NAME                 = "__result";
72 	public static final  String CACHED_BUFFER_LENGTH_NAME       = "length";
73 	public static final  String CACHED_BUFFER_NAME              = "old_buffer";
74 	private static final String OVERLOADED_METHOD_PREFIX        = "n";
75 
getTypedefName(ExecutableElement method)76 	public static String getTypedefName(ExecutableElement method) {
77 		Alternate alt_annotation = method.getAnnotation(Alternate.class);
78 		return (alt_annotation == null ? method.getSimpleName() : alt_annotation.value()) + TYPEDEF_POSTFIX;
79 	}
80 
getFunctionAddressName(TypeElement interface_decl, ExecutableElement method)81 	public static String getFunctionAddressName(TypeElement interface_decl, ExecutableElement method) {
82 		return getFunctionAddressName(interface_decl, method, false);
83 	}
84 
getFunctionAddressName(TypeElement interface_decl, ExecutableElement method, boolean forceAlt)85 	public static String getFunctionAddressName(TypeElement interface_decl, ExecutableElement method, boolean forceAlt) {
86 		final Alternate alt_annotation = method.getAnnotation(Alternate.class);
87 
88                 /* Removed prefix so that we can identify reusable entry points, removed postfix because it's not needed and looks nicer.
89                  String interfaceName = interface_decl.getSimpleName(); // If we add this back, we need to fix @Reuse (add a param for the template name)
90                  if ( alt_annotation == null || (alt_annotation.nativeAlt() && !forceAlt) )
91                  return interfaceName + "_" + method.getSimpleName() + FUNCTION_POINTER_POSTFIX;
92                  else
93                  return interfaceName + "_" + alt_annotation.value() + FUNCTION_POINTER_POSTFIX;
94                  */
95 		if ( alt_annotation == null || (alt_annotation.nativeAlt() && !forceAlt) ) {
96 			return method.getSimpleName().toString();
97 		} else {
98 			return alt_annotation.value();
99 		}
100 	}
101 
isFinal(Element d)102 	public static boolean isFinal(Element d) {
103 		Extension extension_annotation = d.getAnnotation(Extension.class);
104 		return extension_annotation == null || extension_annotation.isFinal();
105 	}
106 
107 	private static class AnnotationMirrorComparator implements Comparator<AnnotationMirror> {
108 
109 		/**
110 		 * Sort annotations.
111 		 */
112 		@Override
compare(AnnotationMirror a1, AnnotationMirror a2)113 		public int compare(AnnotationMirror a1, AnnotationMirror a2) {
114 			String n1 = a1.getAnnotationType().toString();
115 			String n2 = a2.getAnnotationType().toString();
116 			return n1.compareTo(n2);
117 		}
118 
equals(AnnotationMirror a1, AnnotationMirror a2)119 		public boolean equals(AnnotationMirror a1, AnnotationMirror a2) {
120 			return compare(a1, a2) == 0;
121 		}
122 	}
123 
getSortedAnnotations(List<? extends AnnotationMirror> annotations)124 	public static List<AnnotationMirror> getSortedAnnotations(List<? extends AnnotationMirror> annotations) {
125 		List<AnnotationMirror> annotation_list = new ArrayList<AnnotationMirror>(annotations);
126 		Collections.sort(annotation_list, new AnnotationMirrorComparator());
127 		return annotation_list;
128 	}
129 
getReferenceName(TypeElement interface_decl, ExecutableElement method, VariableElement param)130 	public static String getReferenceName(TypeElement interface_decl, ExecutableElement method, VariableElement param) {
131 		return interface_decl.getSimpleName() + "_" + method.getSimpleName() + "_" + param.getSimpleName();
132 	}
133 
isAddressableType(TypeMirror type)134 	public static boolean isAddressableType(TypeMirror type) {
135 		return isAddressableType(getJavaType(type));
136 	}
137 
isAddressableType(Class type)138 	public static boolean isAddressableType(Class type) {
139 		if ( type.isArray() ) {
140 			final Class component_type = type.getComponentType();
141 			return isAddressableTypeImpl(component_type) || PointerWrapper.class.isAssignableFrom(component_type);
142 		}
143 		return isAddressableTypeImpl(type);
144 	}
145 
isAddressableTypeImpl(Class type)146 	private static boolean isAddressableTypeImpl(Class type) {
147 		return Buffer.class.isAssignableFrom(type) || PointerBuffer.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type);
148 	}
149 
getJavaType(TypeMirror type_mirror)150 	public static Class getJavaType(TypeMirror type_mirror) {
151 		JavaTypeTranslator translator = new JavaTypeTranslator();
152 		type_mirror.accept((TypeVisitor)translator, null);
153 		return translator.getType();
154 	}
155 
hasParameterMultipleTypes(VariableElement param)156 	private static boolean hasParameterMultipleTypes(VariableElement param) {
157 		int num_native_annotations = 0;
158 		for ( AnnotationMirror annotation : param.getAnnotationMirrors() ) {
159 			if ( NativeTypeTranslator.getAnnotation(annotation, NativeType.class) != null ) {
160 				num_native_annotations++;
161 			}
162 		}
163 		return num_native_annotations > 1;
164 	}
165 
isParameterMultiTyped(VariableElement param)166 	public static boolean isParameterMultiTyped(VariableElement param) {
167 		boolean result = Buffer.class.equals(Utils.getJavaType(param.asType()));
168 		if ( !result && hasParameterMultipleTypes(param) ) {
169 			throw new RuntimeException(param + " not defined as java.nio.Buffer but has multiple types");
170 		}
171 		return result;
172 	}
173 
findParameter(ExecutableElement method, String name)174 	public static VariableElement findParameter(ExecutableElement method, String name) {
175 		for ( VariableElement param : method.getParameters() ) {
176 			if ( param.getSimpleName().toString().equals(name) ) {
177 				return param;
178 			}
179 		}
180 		throw new RuntimeException("Parameter " + name + " not found");
181 	}
182 
printDocComment(PrintWriter writer, Element decl, ProcessingEnvironment pe)183 	public static void printDocComment(PrintWriter writer, Element decl, ProcessingEnvironment pe) {
184 		final String overloadsComment;
185 		if ( (decl instanceof ExecutableElement) && decl.getAnnotation(Alternate.class) != null ) {
186 			overloadsComment = "Overloads " + decl.getAnnotation(Alternate.class).value() + ".";
187 		} else {
188 			overloadsComment = null;
189 		}
190 
191 		String doc_comment = pe.getElementUtils().getDocComment(decl);
192 		if ( doc_comment != null ) {
193 			final String tab = (decl instanceof TypeElement) ? "" : "\t";
194 			writer.println(tab + "/**");
195 
196 			if ( overloadsComment != null ) {
197 				writer.println("\t * " + overloadsComment);
198 				writer.println("\t * <p>");
199 			}
200 
201 			final StringTokenizer doc_lines = new StringTokenizer(doc_comment, "\n", true);
202 			boolean lastWasNL = false;
203 			while ( doc_lines.hasMoreTokens() ) {
204 				final String t = doc_lines.nextToken();
205 				if ( "\n".equals(t) ) {
206 					if ( lastWasNL ) {
207 						writer.println(tab + " * <p>");
208 					}
209 					lastWasNL = true;
210 				} else {
211 					writer.println(tab + " * " + t);
212 					lastWasNL = false;
213 				}
214 			}
215 
216 			writer.println(tab + " */");
217 		} else if ( overloadsComment != null ) {
218 			writer.println("\t/** " + overloadsComment + " */");
219 		}
220 	}
221 
getParameterAutoAnnotation(VariableElement param)222 	public static AnnotationMirror getParameterAutoAnnotation(VariableElement param) {
223 		for ( AnnotationMirror annotation : param.getAnnotationMirrors() ) {
224 			if ( NativeTypeTranslator.getAnnotation(annotation, Auto.class) != null ) {
225 				return annotation;
226 			}
227 		}
228 		return null;
229 	}
230 
231 	// DISABLED: We always generate indirect methods. (affects OpenAL only at the time of this change)
isMethodIndirect(boolean generate_error_checks, boolean context_specific, ExecutableElement method)232 	public static boolean isMethodIndirect(boolean generate_error_checks, boolean context_specific, ExecutableElement method) {
233 	            /*
234 	             for (VariableElement param : method.getParameters()) {
235                  if (isAddressableType(param.getType()) || getParameterAutoAnnotation(param) != null ||
236                  param.getAnnotation(Constant.class) != null)
237                  return true;
238                  }
239                  return hasMethodBufferObjectParameter(method) || method.getAnnotation(Code.class) != null ||
240                  method.getAnnotation(CachedResult.class) != null ||
241                  (generate_error_checks && method.getAnnotation(NoErrorCheck.class) == null) ||
242                  context_specific;
243                  */
244 		return true;
245 	}
246 
247 	private static final Pattern DOT_PATTERN = Pattern.compile("\\.");
248 
getNativeQualifiedName(String qualified_name)249 	public static String getNativeQualifiedName(String qualified_name) {
250 		return DOT_PATTERN.matcher(qualified_name).replaceAll("_");
251 	}
252 
getQualifiedNativeMethodName(String qualified_class_name, String method_name)253 	public static String getQualifiedNativeMethodName(String qualified_class_name, String method_name) {
254 		// Escape '_' in method name
255 		if ( method_name.indexOf('_') != -1 ) {
256 			method_name = method_name.replace("_", "_1");
257 		}
258 
259 		return "Java_" + getNativeQualifiedName(qualified_class_name) + "_" + method_name;
260 	}
261 
getQualifiedNativeMethodName(String qualified_class_name, ExecutableElement method, boolean generate_error_checks, boolean context_specific)262 	public static String getQualifiedNativeMethodName(String qualified_class_name, ExecutableElement method, boolean generate_error_checks, boolean context_specific) {
263 		String method_name = getSimpleNativeMethodName(method, generate_error_checks, context_specific);
264 		return getQualifiedNativeMethodName(qualified_class_name, method_name);
265 	}
266 
getResultParameter(ExecutableElement method)267 	public static VariableElement getResultParameter(ExecutableElement method) {
268 		VariableElement result_param = null;
269 		for ( VariableElement param : method.getParameters() ) {
270 			if ( param.getAnnotation(Result.class) != null ) {
271 				if ( result_param != null ) {
272 					throw new RuntimeException("Multiple parameters annotated with Result in method " + method);
273 				}
274 				result_param = param;
275 			}
276 		}
277 		return result_param;
278 	}
279 
getMethodReturnType(ExecutableElement method)280 	public static TypeMirror getMethodReturnType(ExecutableElement method) {
281 		TypeMirror result_type;
282 		VariableElement result_param = getResultParameter(method);
283 		if ( result_param != null ) {
284 			result_type = result_param.asType();
285 		} else {
286 			result_type = method.getReturnType();
287 		}
288 		return result_type;
289 	}
290 
getMethodReturnType(ExecutableElement method, GLreturn return_annotation, boolean buffer)291 	public static String getMethodReturnType(ExecutableElement method, GLreturn return_annotation, boolean buffer) {
292 		VariableElement return_param = null;
293 		for ( VariableElement param : method.getParameters() ) {
294 			if ( param.getSimpleName().toString().equals(return_annotation.value()) ) {
295 				return_param = param;
296 				break;
297 			}
298 		}
299 		if ( return_param == null ) {
300 			throw new RuntimeException("The @GLreturn parameter \"" + return_annotation.value() + "\" could not be found in method: " + method);
301 		}
302 
303 		TypeKind kind = NativeTypeTranslator.getPrimitiveKindFromBufferClass(Utils.getJavaType(return_param.asType()));
304 		if ( return_param.getAnnotation(GLboolean.class) != null ) {
305 			kind = TypeKind.BOOLEAN;
306 		}
307 
308 		if ( kind == TypeKind.BYTE && (return_param.getAnnotation(GLchar.class) != null || return_param.getAnnotation(GLcharARB.class) != null) ) {
309 			return "String";
310 		} else {
311 			final String type = JavaTypeTranslator.getPrimitiveClassFromKind(kind).getName();
312 			return buffer ? Character.toUpperCase(type.charAt(0)) + type.substring(1) : type;
313 		}
314 	}
315 
needResultSize(ExecutableElement method)316 	public static boolean needResultSize(ExecutableElement method) {
317 		return getNIOBufferType(getMethodReturnType(method)) != null && method.getAnnotation(AutoSize.class) == null;
318 	}
319 
printExtraCallArguments(PrintWriter writer, ExecutableElement method, String size_parameter_name)320 	public static void printExtraCallArguments(PrintWriter writer, ExecutableElement method, String size_parameter_name) {
321 		writer.print(size_parameter_name);
322 		if ( method.getAnnotation(CachedResult.class) != null ) {
323 			writer.print(", " + CACHED_BUFFER_NAME);
324 		}
325 	}
326 
getClassName(TypeElement interface_decl, String opengl_name)327 	private static String getClassName(TypeElement interface_decl, String opengl_name) {
328 		Extension extension_annotation = interface_decl.getAnnotation(Extension.class);
329 		if ( extension_annotation != null && !"".equals(extension_annotation.className()) ) {
330 			return extension_annotation.className();
331 		}
332 		StringBuilder result = new StringBuilder();
333 		for ( int i = 0; i < opengl_name.length(); i++ ) {
334 			int ch = opengl_name.codePointAt(i);
335 			if ( ch == '_' ) {
336 				i++;
337 				result.appendCodePoint(Character.toUpperCase(opengl_name.codePointAt(i)));
338 			} else {
339 				result.appendCodePoint(ch);
340 			}
341 		}
342 		return result.toString();
343 	}
344 
hasMethodBufferObjectParameter(ExecutableElement method)345 	public static boolean hasMethodBufferObjectParameter(ExecutableElement method) {
346 		for ( VariableElement param : method.getParameters() ) {
347 			if ( param.getAnnotation(BufferObject.class) != null ) {
348 				return true;
349 			}
350 		}
351 		return false;
352 	}
353 
getQualifiedClassName(TypeElement interface_decl)354 	public static String getQualifiedClassName(TypeElement interface_decl) {
355 		return interface_decl.getEnclosingElement().asType().toString() + "." + getSimpleClassName(interface_decl);
356 	}
357 
getSimpleClassName(TypeElement interface_decl)358 	public static String getSimpleClassName(TypeElement interface_decl) {
359 		return getClassName(interface_decl, interface_decl.getSimpleName().toString());
360 	}
361 
getNIOBufferType(TypeMirror t)362 	public static Class<?> getNIOBufferType(TypeMirror t) {
363 		Class<?> param_type = getJavaType(t);
364 		if ( Buffer.class.isAssignableFrom(param_type) ) {
365 			return param_type;
366 		} else if ( param_type == CharSequence.class || param_type == CharSequence[].class || param_type == PointerBuffer.class ) {
367 			return ByteBuffer.class;
368 		} else {
369 			return null;
370 		}
371 	}
372 
getSimpleNativeMethodName(ExecutableElement method, boolean generate_error_checks, boolean context_specific)373 	public static String getSimpleNativeMethodName(ExecutableElement method, boolean generate_error_checks, boolean context_specific) {
374 		String method_name;
375 		Alternate alt_annotation = method.getAnnotation(Alternate.class);
376 		method_name = alt_annotation == null || alt_annotation.nativeAlt() ? method.getSimpleName().toString() : alt_annotation.value();
377 		if ( isMethodIndirect(generate_error_checks, context_specific, method) ) {
378 			method_name = OVERLOADED_METHOD_PREFIX + method_name;
379 		}
380 		return method_name;
381 	}
382 
isReturnParameter(ExecutableElement method, VariableElement param)383 	static boolean isReturnParameter(ExecutableElement method, VariableElement param) {
384 		GLreturn string_annotation = method.getAnnotation(GLreturn.class);
385 		if ( string_annotation == null || !string_annotation.value().equals(param.getSimpleName().toString()) ) {
386 			return false;
387 		}
388 
389 		if ( param.getAnnotation(OutParameter.class) == null ) {
390 			throw new RuntimeException("The parameter specified in @GLreturn is not annotated with @OutParameter in method: " + method);
391 		}
392 
393 		if ( param.getAnnotation(Check.class) != null ) {
394 			throw new RuntimeException("The parameter specified in @GLreturn is annotated with @Check in method: " + method);
395 		}
396 
397 		if ( param.getAnnotation(GLchar.class) != null && Utils.getJavaType(param.asType()).equals(ByteBuffer.class) && string_annotation.maxLength().length() == 0 ) {
398 			throw new RuntimeException("The @GLreturn annotation is missing a maxLength parameter in method: " + method);
399 		}
400 
401 		return true;
402 	}
403 
getStringOffset(ExecutableElement method, VariableElement param)404 	static String getStringOffset(ExecutableElement method, VariableElement param) {
405 		String offset = null;
406 		for ( VariableElement p : method.getParameters() ) {
407 			if ( param != null && p.getSimpleName().equals(param.getSimpleName()) ) {
408 				break;
409 			}
410 
411 			if ( p.getAnnotation(NullTerminated.class) != null ) {
412 				continue;
413 			}
414 
415 			final Class type = Utils.getJavaType(p.asType());
416 			if ( type.equals(CharSequence.class) ) {
417 				if ( offset == null ) {
418 					offset = p.getSimpleName() + ".length()";
419 				} else {
420 					offset += " + " + p.getSimpleName() + ".length()";
421 				}
422 				//if ( p.getAnnotation(NullTerminated.class) != null ) offset += " + 1";
423 			} else if ( type.equals(CharSequence[].class) ) {
424 				if ( offset == null ) {
425 					offset = "APIUtil.getTotalLength(" + p.getSimpleName() + ")";
426 				} else {
427 					offset += " + APIUtil.getTotalLength(" + p.getSimpleName() + ")";
428 				}
429 				//if ( p.getAnnotation(NullTerminated.class) != null ) offset += " + " + p.getSimpleName() + ".length";
430 			}
431 
432 		}
433 		return offset;
434 	}
435 
printGLReturnPre(PrintWriter writer, ExecutableElement method, GLreturn return_annotation, TypeMap type_map)436 	static void printGLReturnPre(PrintWriter writer, ExecutableElement method, GLreturn return_annotation, TypeMap type_map) {
437 		final String return_type = getMethodReturnType(method, return_annotation, true);
438 
439 		if ( "String".equals(return_type) ) {
440 			if ( !return_annotation.forceMaxLength() ) {
441 				writer.println("IntBuffer " + return_annotation.value() + "_length = APIUtil.getLengths(" + type_map.getAPIUtilParam(false) + ");");
442 				writer.print("\t\t");
443 			}
444 			writer.print("ByteBuffer " + return_annotation.value() + " = APIUtil.getBufferByte(" + type_map.getAPIUtilParam(true) + return_annotation.maxLength());
445 	        /*
446              Params that use the return buffer will advance its position while filling it. When we return, the position will be
447              at the right spot for grabbing the returned string bytes. We only have to make sure that the original buffer was
448              large enough to hold everything, so that no re-allocations happen while filling.
449              */
450 			final String offset = getStringOffset(method, null);
451 			if ( offset != null ) {
452 				writer.print(" + " + offset);
453 			}
454 			writer.println(");");
455 		} else {
456 			final String buffer_type = "Boolean".equals(return_type) ? "Byte" : return_type;
457 			writer.print(buffer_type + "Buffer " + return_annotation.value() + " = APIUtil.getBuffer" + buffer_type + "(" + type_map.getAPIUtilParam(false));
458 			if ( "Byte".equals(buffer_type) ) {
459 				writer.print((type_map.getAPIUtilParam(false).length() > 0 ? ", " : "") + "1");
460 			}
461 			writer.println(");");
462 		}
463 
464 		final Code code_annotation = method.getAnnotation(Code.class);
465 		if ( code_annotation != null && code_annotation.tryBlock() ) {
466 			writer.println("\t\ttry {");
467 			writer.print("\t\t\t");
468 		} else {
469 			writer.print("\t\t");
470 		}
471 	}
472 
printGLReturnPost(PrintWriter writer, ExecutableElement method, GLreturn return_annotation, TypeMap type_map)473 	static void printGLReturnPost(PrintWriter writer, ExecutableElement method, GLreturn return_annotation, TypeMap type_map) {
474 		final String return_type = getMethodReturnType(method, return_annotation, true);
475 
476 		if ( "String".equals(return_type) ) {
477 			writer.print("\t\t" + return_annotation.value() + ".limit(");
478 			final String offset = getStringOffset(method, null);
479 			if ( offset != null ) {
480 				writer.print(offset + " + ");
481 			}
482 			if ( return_annotation.forceMaxLength() ) {
483 				writer.print(return_annotation.maxLength());
484 			} else {
485 				writer.print(return_annotation.value() + "_length.get(0)");
486 			}
487 			writer.println(");");
488 			writer.println("\t\treturn APIUtil.getString(" + type_map.getAPIUtilParam(true) + return_annotation.value() + ");");
489 		} else {
490 			writer.print("\t\treturn " + return_annotation.value() + ".get(0)");
491 			if ( "Boolean".equals(return_type) ) {
492 				writer.print(" == 1");
493 			}
494 			writer.println(";");
495 		}
496 	}
497 
getFields(TypeElement d)498 	public static Collection<VariableElement> getFields(TypeElement d) {
499 		return ElementFilter.fieldsIn(new LinkedHashSet<Element>(d.getEnclosedElements()));
500 	}
501 
getMethods(TypeElement d)502 	public static Collection<ExecutableElement> getMethods(TypeElement d) {
503 		return ElementFilter.methodsIn(new LinkedHashSet<Element>(d.getEnclosedElements()));
504 	}
505 
506 }
507