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 * This class represent a parameter configuration. There are multiple TypeInfos 37 * in case of multityped parameters. 38 * 39 * @author elias_naur <elias_naur@users.sourceforge.net> 40 * @version $Revision$ $Id$ 41 */ 42 import org.lwjgl.PointerBuffer; 43 import org.lwjgl.util.generator.opengl.GLvoid; 44 45 import java.lang.annotation.Annotation; 46 import java.nio.*; 47 import java.util.*; 48 import javax.lang.model.element.AnnotationMirror; 49 import javax.lang.model.element.ExecutableElement; 50 import javax.lang.model.element.VariableElement; 51 import javax.lang.model.type.TypeKind; 52 import javax.lang.model.type.TypeMirror; 53 54 public class TypeInfo { 55 56 public static final String UNSIGNED_PARAMETER_NAME = "unsigned"; 57 58 private final Signedness signedness; 59 private final Class type; 60 private final String auto_type; 61 TypeInfo(Class type, Signedness signedness, String auto_type)62 private TypeInfo(Class type, Signedness signedness, String auto_type) { 63 this.type = type; 64 this.signedness = signedness; 65 this.auto_type = auto_type; 66 } 67 getType()68 public Class getType() { 69 return type; 70 } 71 getSignedness()72 public Signedness getSignedness() { 73 return signedness; 74 } 75 getAutoType()76 public String getAutoType() { 77 if ( auto_type == null ) { 78 throw new RuntimeException("No auto type assigned"); 79 } 80 return auto_type; 81 } 82 getTypeFromPrimitiveKind(TypeKind kind)83 private static Class getTypeFromPrimitiveKind(TypeKind kind) { 84 Class type; 85 switch ( kind ) { 86 case LONG: 87 type = long.class; 88 break; 89 case INT: 90 type = int.class; 91 break; 92 case FLOAT: 93 type = float.class; 94 break; 95 case DOUBLE: 96 type = double.class; 97 break; 98 case SHORT: 99 type = short.class; 100 break; 101 case BYTE: 102 type = byte.class; 103 break; 104 case BOOLEAN: 105 type = boolean.class; 106 break; 107 default: 108 throw new RuntimeException(kind + " is not allowed"); 109 } 110 return type; 111 } 112 getBufferTypeFromPrimitiveKind(TypeKind kind, AnnotationMirror annotation)113 private static Class getBufferTypeFromPrimitiveKind(TypeKind kind, AnnotationMirror annotation) { 114 Class type; 115 switch ( kind ) { 116 case INT: 117 type = IntBuffer.class; 118 break; 119 case FLOAT: 120 type = FloatBuffer.class; 121 break; 122 case DOUBLE: 123 type = DoubleBuffer.class; 124 break; 125 case SHORT: 126 type = ShortBuffer.class; 127 break; 128 case LONG: 129 if ( annotation.getAnnotationType().asElement().getAnnotation(PointerType.class) != null ) { 130 type = PointerBuffer.class; 131 } else { 132 type = LongBuffer.class; 133 } 134 break; 135 case BYTE: /* fall through */ 136 137 case BOOLEAN: 138 type = ByteBuffer.class; 139 break; 140 default: 141 throw new RuntimeException(kind + " is not allowed"); 142 } 143 return type; 144 } 145 getDefaultTypeInfo(TypeMirror t)146 private static TypeInfo getDefaultTypeInfo(TypeMirror t) { 147 Class java_type = Utils.getJavaType(t); 148 return new TypeInfo(java_type, Signedness.NONE, null); 149 } 150 getDefaultTypeInfoMap(ExecutableElement method)151 public static Map<VariableElement, TypeInfo> getDefaultTypeInfoMap(ExecutableElement method) { 152 Map<VariableElement, TypeInfo> map = new HashMap<VariableElement, TypeInfo>(); 153 for ( VariableElement param : method.getParameters() ) { 154 TypeInfo type_info = getDefaultTypeInfo(param.asType()); 155 map.put(param, type_info); 156 } 157 return map; 158 } 159 getTypeInfos(TypeMap type_map, VariableElement param)160 private static Collection<TypeInfo> getTypeInfos(TypeMap type_map, VariableElement param) { 161 List<? extends AnnotationMirror> annotations = Utils.getSortedAnnotations(param.getAnnotationMirrors()); 162 GLvoid void_annotation = param.getAnnotation(GLvoid.class); 163 164 Map<Class, TypeInfo> types = new HashMap<Class, TypeInfo>(); 165 Collection<TypeInfo> multityped_result = new ArrayList<TypeInfo>(); 166 boolean add_default_type = true; 167 for ( AnnotationMirror annotation : annotations ) { 168 NativeType native_type_annotation = NativeTypeTranslator.getAnnotation(annotation, NativeType.class); 169 if ( native_type_annotation != null ) { 170 Class<? extends Annotation> annotation_type = NativeTypeTranslator.getClassFromType(annotation.getAnnotationType()); 171 Signedness signedness = type_map.getSignednessFromType(annotation_type); 172 Class inverse_type = type_map.getInverseType(annotation_type); 173 String auto_type = type_map.getAutoTypeFromAnnotation(annotation); 174 if ( inverse_type != null ) { 175 if ( types.containsKey(inverse_type) ) { 176 TypeInfo inverse_type_info = types.get(inverse_type); 177 String inverse_auto_type = inverse_type_info.getAutoType(); 178 auto_type = signedness == Signedness.UNSIGNED ? auto_type + " : " + inverse_auto_type : inverse_auto_type + " : " + auto_type; 179 auto_type = UNSIGNED_PARAMETER_NAME + " ? " + auto_type; 180 signedness = Signedness.BOTH; 181 types.remove(inverse_type); 182 multityped_result.remove(inverse_type_info); 183 } 184 } 185 Class type; 186 TypeKind kind; 187 kind = void_annotation == null ? type_map.getPrimitiveTypeFromNativeType(annotation_type) : void_annotation.value(); 188 if ( Utils.getNIOBufferType(param.asType()) != null ) { 189 type = getBufferTypeFromPrimitiveKind(kind, annotation); 190 } else { 191 type = getTypeFromPrimitiveKind(kind); 192 } 193 TypeInfo type_info = new TypeInfo(type, signedness, auto_type); 194 types.put(annotation_type, type_info); 195 multityped_result.add(type_info); 196 add_default_type = false; 197 } 198 } 199 if ( add_default_type ) { 200 TypeInfo default_type_info = getDefaultTypeInfo(param.asType()); 201 Collection<TypeInfo> result = new ArrayList<TypeInfo>(); 202 result.add(default_type_info); 203 return result; 204 } else { 205 return multityped_result; 206 } 207 } 208 getTypeInfoMap(TypeMap type_map, ExecutableElement method)209 private static Map<VariableElement, Collection<TypeInfo>> getTypeInfoMap(TypeMap type_map, ExecutableElement method) { 210 Map<VariableElement, Collection<TypeInfo>> map = new HashMap<VariableElement, Collection<TypeInfo>>(); 211 for ( VariableElement param : method.getParameters() ) { 212 Collection<TypeInfo> types = getTypeInfos(type_map, param); 213 map.put(param, types); 214 } 215 return map; 216 } 217 getTypeInfoCrossProduct(TypeMap type_map, ExecutableElement method)218 public static Collection<Map<VariableElement, TypeInfo>> getTypeInfoCrossProduct(TypeMap type_map, ExecutableElement method) { 219 List<? extends VariableElement> parameter_collection = method.getParameters(); 220 Collection<Map<VariableElement, TypeInfo>> cross_product = new ArrayList<Map<VariableElement, TypeInfo>>(); 221 getCrossProductRecursive(0, parameter_collection, getTypeInfoMap(type_map, method), 222 new HashMap<VariableElement, TypeInfo>(), cross_product); 223 return cross_product; 224 } 225 getCrossProductRecursive(int index, List<? extends VariableElement> parameters, Map<VariableElement, Collection<TypeInfo>> typeinfos_map, Map<VariableElement, TypeInfo> current_instance, Collection<Map<VariableElement, TypeInfo>> cross_product)226 private static void getCrossProductRecursive(int index, List<? extends VariableElement> parameters, Map<VariableElement, Collection<TypeInfo>> typeinfos_map, Map<VariableElement, TypeInfo> current_instance, Collection<Map<VariableElement, TypeInfo>> cross_product) { 227 if ( index == parameters.size() ) { 228 /** 229 * the last parameter is treated as multi-type only 230 */ 231 cross_product.add(current_instance); 232 return; 233 } 234 VariableElement param = parameters.get(index); 235 Collection<TypeInfo> typeinfos = typeinfos_map.get(param); 236 if ( typeinfos != null ) { 237 for ( TypeInfo typeinfo : typeinfos ) { 238 Map<VariableElement, TypeInfo> instance = new HashMap<VariableElement, TypeInfo>(current_instance); 239 instance.put(param, typeinfo); 240 getCrossProductRecursive(index + 1, parameters, typeinfos_map, instance, cross_product); 241 } 242 } 243 } 244 } 245