001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.generator.as3.reflect; 022 023import java.lang.annotation.Annotation; 024import java.lang.reflect.Method; 025import java.lang.reflect.ParameterizedType; 026import java.lang.reflect.Type; 027import java.util.Map; 028 029import org.granite.generator.as3.ClientType; 030import org.granite.generator.as3.PropertyType; 031import org.granite.generator.util.GenericTypeUtil; 032import org.granite.messaging.service.annotations.Param; 033import org.granite.tide.data.Lazy; 034import org.granite.util.ClassUtil; 035 036/** 037 * @author Franck WOLFF 038 */ 039public class JavaMethod extends JavaMember<Method> { 040 041 public enum MethodType { 042 GETTER, 043 SETTER, 044 OTHER 045 } 046 047 private final String name; 048 private final boolean override; 049 private final MethodType type; 050 private final String options; 051 private final Class<?> returnType; 052 private final Class<?>[] parameterTypes; 053 private final ClientType clientReturnType; 054 private final ClientType[] clientParameterTypes; 055 private final String[] clientParameterNames; 056 private final String[] clientParameterOptions; 057 058 public JavaMethod(Method method, MethodType type) { 059 this(method, type, null, null); 060 } 061 062 public JavaMethod(Method method, MethodType type, JavaTypeFactory provider) { 063 this(method, type, provider, null); 064 } 065 066 public JavaMethod(Method method, MethodType type, JavaTypeFactory provider, ParameterizedType[] declaringTypes) { 067 super(method); 068 069 Class<?> objectClass = Object.class; 070 try { 071 objectClass = method.getDeclaringClass().getClassLoader().loadClass(Object.class.getCanonicalName()); 072 } 073 catch (Exception e) { 074 } 075 076 this.name = method.getName(); 077 078 // This part figure out if an ActionScript3 accessor should be marked as override. 079 Class<?> superclass = method.getDeclaringClass().getSuperclass(); 080 boolean override = false; 081 if (superclass != null && superclass != objectClass) { 082 try { 083 Method superMethod = superclass.getMethod(method.getName(), method.getParameterTypes()); 084 085 // if the super method is declared by an interface, check if we have a superclass that 086 // implements this interface. 087 if (superMethod.getDeclaringClass().isInterface()) 088 override = superMethod.getDeclaringClass().isAssignableFrom(superclass); 089 // if the super method is declared by a class, check if its declaring class implements, 090 // directly or not, an interface with a method with the same signature. 091 else { 092 for (Class<?> sc = superMethod.getDeclaringClass(); sc != null; sc = sc.getSuperclass()) { 093 for (Class<?> interfaze : sc.getInterfaces()) { 094 try { 095 interfaze.getMethod(method.getName(), method.getParameterTypes()); 096 override = true; 097 break; 098 } 099 catch (NoSuchMethodException e) { 100 // continue... 101 } 102 } 103 if (override) 104 break; 105 } 106 } 107 } catch (NoSuchMethodException e) { 108 // continue... 109 } 110 } 111 this.override = override; 112 113 this.type = type; 114 115 if (method.isAnnotationPresent(Lazy.class)) 116 this.options = "Lazy"; 117 else 118 this.options = null; 119 120 if (type == MethodType.OTHER && provider != null) { 121 if (method.getReturnType() == void.class) { 122 this.returnType = Void.class; 123 this.clientReturnType = provider.getClientType(Void.class, null, null, PropertyType.SIMPLE); 124 } 125 else { 126 Type genericType = GenericTypeUtil.resolveTypeVariable(method.getGenericReturnType(), method.getDeclaringClass(), declaringTypes); 127 genericType = GenericTypeUtil.primitiveToWrapperType(genericType); 128 this.returnType = ClassUtil.classOfType(genericType); 129 130 ClientType returnType = provider.getClientType(genericType, method.getDeclaringClass(), declaringTypes, PropertyType.SIMPLE); 131 if (returnType == null) 132 returnType = provider.getAs3Type(this.returnType); 133 clientReturnType = returnType; 134 } 135 136 this.parameterTypes = method.getParameterTypes(); 137 this.clientParameterTypes = new ClientType[this.parameterTypes.length]; 138 this.clientParameterNames = new String[this.parameterTypes.length]; 139 this.clientParameterOptions = new String[this.parameterTypes.length]; 140 for (int i = 0; i < this.parameterTypes.length; i++) { 141 clientParameterNames[i] = getParamName(method, i); 142 if (Map.class.isAssignableFrom(parameterTypes[i])) 143 clientParameterTypes[i] = provider.getClientType(Object.class, null, null, PropertyType.SIMPLE); 144 else { 145 Type genericType = GenericTypeUtil.resolveTypeVariable(method.getGenericParameterTypes()[i], method.getDeclaringClass(), declaringTypes); 146 parameterTypes[i] = ClassUtil.classOfType(genericType); 147 148 ClientType paramType = provider.getClientType(genericType, method.getDeclaringClass(), declaringTypes, PropertyType.SIMPLE); 149 if (paramType == null) 150 paramType = provider.getAs3Type(parameterTypes[i]); 151 clientParameterTypes[i] = paramType; 152 } 153 154 Annotation[] annotations = method.getParameterAnnotations()[i]; 155 for (Annotation annotation : annotations) { 156 if (annotation.annotationType().equals(Lazy.class)) { 157 clientParameterOptions[i] = "Lazy"; 158 break; 159 } 160 } 161 } 162 } 163 else { 164 this.returnType = null; 165 this.parameterTypes = null; 166 this.clientReturnType = null; 167 this.clientParameterTypes = null; 168 this.clientParameterNames = null; 169 this.clientParameterOptions = null; 170 } 171 } 172 173 private String getParamName(Method method, int paramIndex) { 174 Annotation[][] annotations = method.getParameterAnnotations(); 175 if (annotations != null && annotations.length > paramIndex && annotations[paramIndex] != null) { 176 for (Annotation annotation : annotations[paramIndex]) { 177 if (annotation.annotationType().equals(Param.class)) 178 return ((Param)annotation).value(); 179 } 180 } 181 return "arg" + paramIndex; 182 } 183 184 public boolean isOverride() { 185 return override; 186 } 187 188 public MethodType getType() { 189 return type; 190 } 191 192 public String getOptions() { 193 return options; 194 } 195 196 public String getTypeName() { 197 return type.name(); 198 } 199 200 @Override 201 public String getName() { 202 return name; 203 } 204 205 public Class<?> getReturnType() { 206 return returnType; 207 } 208 209 public Class<?>[] getParameterTypes() { 210 return parameterTypes; 211 } 212 213 public ClientType[] getAs3ParameterTypes() { 214 return clientParameterTypes; 215 } 216 217 public String[] getAs3ParameterNames() { 218 return clientParameterNames; 219 } 220 221 public String[] getAs3ParameterOptions() { 222 return clientParameterOptions; 223 } 224 225 public ClientType getClientReturnType() { 226 return clientReturnType; 227 } 228 229 public ClientType[] getClientParameterTypes() { 230 return clientParameterTypes; 231 } 232 233 public String[] getClientParameterNames() { 234 return clientParameterNames; 235 } 236 237 public String[] getClientParameterOptions() { 238 return clientParameterOptions; 239 } 240}