001 /*
002 GRANITE DATA SERVICES
003 Copyright (C) 2007-2010 ADEQUATE SYSTEMS SARL
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
021 package org.granite.generator.as3.reflect;
022
023 import java.lang.annotation.Annotation;
024 import java.lang.reflect.Method;
025 import java.util.Map;
026
027 import org.granite.generator.as3.As3Type;
028 import org.granite.messaging.service.annotations.Param;
029
030 /**
031 * @author Franck WOLFF
032 */
033 public class JavaMethod extends JavaMember<Method> {
034
035 public enum MethodType {
036 GETTER,
037 SETTER,
038 OTHER
039 }
040
041 private final String name;
042 private final boolean override;
043 private final MethodType type;
044 private final Class<?>[] parameterTypes;
045 private final As3Type[] as3ParameterTypes;
046 private final String[] as3ParameterNames;
047
048 public JavaMethod(Method method, MethodType type) {
049 this(method, type, null);
050 }
051
052 public JavaMethod(Method method, MethodType type, JavaTypeFactory provider) {
053 super(method);
054
055 Class<?> objectClass = Object.class;
056 try {
057 objectClass = method.getDeclaringClass().getClassLoader().loadClass(Object.class.getCanonicalName());
058 }
059 catch (Exception e) {
060 }
061
062 this.name = method.getName();
063
064 // This part figure out if an ActionScript3 accessor should be marked as override.
065 Class<?> superclass = method.getDeclaringClass().getSuperclass();
066 boolean override = false;
067 if (superclass != null && superclass != objectClass) {
068 try {
069 Method superMethod = superclass.getMethod(method.getName(), method.getParameterTypes());
070
071 // if the super method is declared by an interface, check if we have a superclass that
072 // implements this interface.
073 if (superMethod.getDeclaringClass().isInterface())
074 override = superMethod.getDeclaringClass().isAssignableFrom(superclass);
075 // if the super method is declared by a class, check if its declaring class implements,
076 // directly or not, an interface with a method with the same signature.
077 else {
078 for (Class<?> sc = superMethod.getDeclaringClass(); sc != null; sc = sc.getSuperclass()) {
079 for (Class<?> interfaze : sc.getInterfaces()) {
080 try {
081 interfaze.getMethod(method.getName(), method.getParameterTypes());
082 override = true;
083 break;
084 }
085 catch (NoSuchMethodException e) {
086 // continue...
087 }
088 }
089 if (override)
090 break;
091 }
092 }
093 } catch (NoSuchMethodException e) {
094 // continue...
095 }
096 }
097 this.override = override;
098
099 this.type = type;
100
101 if (type == MethodType.OTHER && provider != null) {
102 this.parameterTypes = method.getParameterTypes();
103 this.as3ParameterTypes = new As3Type[this.parameterTypes.length];
104 this.as3ParameterNames = new String[this.parameterTypes.length];
105 for (int i = 0; i < this.parameterTypes.length; i++) {
106 as3ParameterNames[i] = getParamName(method, i);
107 if (Map.class.isAssignableFrom(parameterTypes[i]))
108 as3ParameterTypes[i] = As3Type.OBJECT;
109 else
110 as3ParameterTypes[i] = provider.getAs3Type(this.parameterTypes[i]);
111 }
112 }
113 else {
114 this.parameterTypes = null;
115 this.as3ParameterTypes = null;
116 this.as3ParameterNames = null;
117 }
118 }
119
120 private String getParamName(Method method, int paramIndex) {
121 Annotation[][] annotations = method.getParameterAnnotations();
122 if (annotations != null && annotations.length > paramIndex && annotations[paramIndex] != null) {
123 for (Annotation annotation : annotations[paramIndex]) {
124 if (annotation.annotationType().equals(Param.class))
125 return ((Param)annotation).value();
126 }
127 }
128 return "arg" + paramIndex;
129 }
130
131 public boolean isOverride() {
132 return override;
133 }
134
135 public MethodType getType() {
136 return type;
137 }
138
139 public String getTypeName() {
140 return type.name();
141 }
142
143 @Override
144 public String getName() {
145 return name;
146 }
147
148 public Class<?>[] getParameterTypes() {
149 return parameterTypes;
150 }
151
152 public As3Type[] getAs3ParameterTypes() {
153 return as3ParameterTypes;
154 }
155
156 public String[] getAs3ParameterNames() {
157 return as3ParameterNames;
158 }
159 }