/** * GRANITE DATA SERVICES * Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S. * * This file is part of the Granite Data Services Platform. * * Granite Data Services is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * Granite Data Services is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA, or see <http://www.gnu.org/licenses/>. */ package org.granite.generator.as3.reflect; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.granite.generator.as3.ClientType; import org.granite.generator.as3.PropertyType; import org.granite.generator.util.GenericTypeUtil; import org.granite.messaging.service.annotations.Param; import org.granite.tide.data.Lazy; import org.granite.util.ClassUtil; /** * @author Franck WOLFF */ public class JavaMethod extends JavaMember<Method> { public enum MethodType { GETTER, SETTER, OTHER } private final String name; private final boolean override; private final MethodType type; private final String options; private final Class<?> returnType; private final Class<?>[] parameterTypes; private final ClientType clientReturnType; private final ClientType[] clientParameterTypes; private final String[] clientParameterNames; private final String[] clientParameterOptions; private final Set<ClientType> clientAnnotationTypes = new HashSet<ClientType>(); public JavaMethod(Method method, MethodType type) { this(method, type, null, null); } public JavaMethod(Method method, MethodType type, JavaTypeFactory provider) { this(method, type, provider, null); } public JavaMethod(Method method, MethodType type, JavaTypeFactory provider, ParameterizedType[] declaringTypes) { super(method); Class<?> objectClass = Object.class; try { objectClass = method.getDeclaringClass().getClassLoader().loadClass(Object.class.getCanonicalName()); } catch (Exception e) { } this.name = method.getName(); // This part figure out if an ActionScript3 accessor should be marked as override. Class<?> superclass = method.getDeclaringClass().getSuperclass(); boolean override = false; if (superclass != null && superclass != objectClass) { try { Method superMethod = superclass.getMethod(method.getName(), method.getParameterTypes()); // if the super method is declared by an interface, check if we have a superclass that // implements this interface. if (superMethod.getDeclaringClass().isInterface()) override = superMethod.getDeclaringClass().isAssignableFrom(superclass); // if the super method is declared by a class, check if its declaring class implements, // directly or not, an interface with a method with the same signature. else { for (Class<?> sc = superMethod.getDeclaringClass(); sc != null; sc = sc.getSuperclass()) { for (Class<?> interfaze : sc.getInterfaces()) { try { interfaze.getMethod(method.getName(), method.getParameterTypes()); override = true; break; } catch (NoSuchMethodException e) { // continue... } } if (override) break; } } } catch (NoSuchMethodException e) { // continue... } } this.override = override; this.type = type; if (method.isAnnotationPresent(Lazy.class)) { this.options = "Lazy"; this.clientAnnotationTypes.add(provider.getClientType(Lazy.class, null, null, null)); } else this.options = null; if (type == MethodType.OTHER && provider != null) { if (method.getReturnType() == void.class) { this.returnType = Void.class; this.clientReturnType = provider.getClientType(Void.class, null, null, PropertyType.SIMPLE); } else { Type genericType = GenericTypeUtil.resolveTypeVariable(method.getGenericReturnType(), method.getDeclaringClass(), declaringTypes); genericType = GenericTypeUtil.primitiveToWrapperType(genericType); this.returnType = ClassUtil.classOfType(genericType); ClientType returnType = provider.getClientType(genericType, method.getDeclaringClass(), declaringTypes, PropertyType.SIMPLE); if (returnType == null) returnType = provider.getAs3Type(this.returnType); clientReturnType = returnType; } this.parameterTypes = method.getParameterTypes(); this.clientParameterTypes = new ClientType[this.parameterTypes.length]; this.clientParameterNames = new String[this.parameterTypes.length]; this.clientParameterOptions = new String[this.parameterTypes.length]; for (int i = 0; i < this.parameterTypes.length; i++) { clientParameterNames[i] = getParamName(method, i); if (Map.class.isAssignableFrom(parameterTypes[i])) clientParameterTypes[i] = provider.getClientType(Object.class, null, null, PropertyType.SIMPLE); else { Type genericType = GenericTypeUtil.resolveTypeVariable(method.getGenericParameterTypes()[i], method.getDeclaringClass(), declaringTypes); parameterTypes[i] = ClassUtil.classOfType(genericType); ClientType paramType = provider.getClientType(genericType, method.getDeclaringClass(), declaringTypes, PropertyType.SIMPLE); if (paramType == null) paramType = provider.getAs3Type(parameterTypes[i]); clientParameterTypes[i] = paramType; } Annotation[] annotations = method.getParameterAnnotations()[i]; for (Annotation annotation : annotations) { if (annotation.annotationType().equals(Lazy.class)) { clientParameterOptions[i] = "Lazy"; this.clientAnnotationTypes.add(provider.getClientType(Lazy.class, null, null, null)); break; } } } } else { this.returnType = null; this.parameterTypes = null; this.clientReturnType = null; this.clientParameterTypes = null; this.clientParameterNames = null; this.clientParameterOptions = null; } } private String getParamName(Method method, int paramIndex) { Annotation[][] annotations = method.getParameterAnnotations(); if (annotations != null && annotations.length > paramIndex && annotations[paramIndex] != null) { for (Annotation annotation : annotations[paramIndex]) { if (annotation.annotationType().equals(Param.class)) return ((Param)annotation).value(); } } return "arg" + paramIndex; } public boolean isOverride() { return override; } public MethodType getType() { return type; } public String getOptions() { return options; } public String getTypeName() { return type.name(); } @Override public String getName() { return name; } public Class<?> getReturnType() { return returnType; } public Class<?>[] getParameterTypes() { return parameterTypes; } public ClientType[] getAs3ParameterTypes() { return clientParameterTypes; } public String[] getAs3ParameterNames() { return clientParameterNames; } public String[] getAs3ParameterOptions() { return clientParameterOptions; } public ClientType getClientReturnType() { return clientReturnType; } public ClientType[] getClientParameterTypes() { return clientParameterTypes; } public String[] getClientParameterNames() { return clientParameterNames; } public String[] getClientParameterOptions() { return clientParameterOptions; } public Set<ClientType> getClientAnnotationTypes() { return clientAnnotationTypes; } }