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