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