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.ParameterizedType;
025 import java.lang.reflect.Type;
026 import java.lang.reflect.TypeVariable;
027 import java.util.ArrayList;
028 import java.util.Arrays;
029 import java.util.List;
030
031 import org.granite.generator.as3.ClientType;
032 import org.granite.messaging.amf.io.util.externalizer.annotation.ExternalizedProperty;
033 import org.granite.util.ClassUtil;
034
035 /**
036 * @author Franck WOLFF
037 */
038 public class JavaMethodProperty implements JavaProperty {
039
040 private final String name;
041 private final JavaMethod readMethod;
042 private final JavaMethod writeMethod;
043 private final Class<?> type;
044 private final Type genericType;
045 private final ClientType clientType;
046 private final boolean externalizedProperty;
047
048 public JavaMethodProperty(JavaTypeFactory provider, String name, JavaMethod readMethod, JavaMethod writeMethod) {
049 this(provider, name, readMethod, writeMethod, null);
050 }
051
052 public JavaMethodProperty(JavaTypeFactory provider, String name, JavaMethod readMethod, JavaMethod writeMethod, ParameterizedType declaringType) {
053 if (name == null || (readMethod == null && writeMethod == null))
054 throw new NullPointerException("Invalid parameters");
055 this.name = name;
056 this.readMethod = readMethod;
057 this.writeMethod = writeMethod;
058 Type genericType = (
059 readMethod != null ?
060 readMethod.getMember().getGenericReturnType() :
061 writeMethod.getMember().getGenericParameterTypes()[0]
062 );
063 Class<?> declaringClass = readMethod != null ? readMethod.getMember().getDeclaringClass() : writeMethod.getMember().getDeclaringClass();
064 if (genericType instanceof TypeVariable && declaringType != null) {
065 int index = -1;
066 for (int i = 0; i < declaringClass.getTypeParameters().length; i++) {
067 if (declaringClass.getTypeParameters()[i] == genericType) {
068 index = i;
069 break;
070 }
071 }
072 if (index >= 0 && index < declaringType.getActualTypeArguments().length)
073 genericType = declaringType.getActualTypeArguments()[index];
074 }
075 this.type = ClassUtil.classOfType(genericType);
076 this.genericType = genericType;
077 ClientType clientType = provider.getClientType(genericType, null, null, true);
078 if (clientType == null)
079 clientType = provider.getAs3Type(type);
080 this.clientType = clientType;
081 this.externalizedProperty = (
082 readMethod != null &&
083 ClassUtil.isAnnotationPresent(readMethod.getMember(), ExternalizedProperty.class)
084 );
085 }
086
087 @Override
088 public String getName() {
089 return name;
090 }
091
092 @Override
093 public String getCapitalizedName() {
094 return getName().substring(0, 1).toUpperCase() + getName().substring(1);
095 }
096
097 @Override
098 public Class<?> getType() {
099 return type;
100 }
101
102 public Type getGenericType() {
103 return genericType;
104 }
105
106 @Override
107 public Type[] getGenericTypes() {
108 Type type = readMethod != null ? readMethod.getMember().getGenericReturnType() : writeMethod.getMember().getGenericParameterTypes()[0];
109 if (!(type instanceof ParameterizedType))
110 return null;
111 return ((ParameterizedType)type).getActualTypeArguments();
112 }
113
114 @Override
115 public boolean isReadable() {
116 return (readMethod != null);
117 }
118
119 @Override
120 public boolean isWritable() {
121 return (writeMethod != null);
122 }
123
124 @Override
125 public boolean isExternalizedProperty() {
126 return externalizedProperty;
127 }
128
129 @Override
130 public boolean isEnum() {
131 return (type.isEnum() || Enum.class.getName().equals(type.getName()));
132 }
133
134 @Override
135 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
136 return (
137 (readMethod != null && readMethod.getMember().isAnnotationPresent(annotationClass)) ||
138 (writeMethod != null && writeMethod.getMember().isAnnotationPresent(annotationClass))
139 );
140 }
141
142 @Override
143 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
144 T annotation = null;
145 if (readMethod != null) {
146 annotation = readMethod.getMember().getAnnotation(annotationClass);
147 if (annotation != null)
148 return annotation;
149 }
150 if (writeMethod != null) {
151 annotation = writeMethod.getMember().getAnnotation(annotationClass);
152 if (annotation != null)
153 return annotation;
154 }
155 return null;
156 }
157
158 @Override
159 public Annotation[] getDeclaredAnnotations() {
160 List<Annotation> annos = new ArrayList<Annotation>();
161 if (readMethod != null)
162 annos.addAll(Arrays.asList(readMethod.getMember().getDeclaredAnnotations()));
163 if (writeMethod != null)
164 annos.addAll(Arrays.asList(writeMethod.getMember().getDeclaredAnnotations()));
165 return annos.toArray(new Annotation[0]);
166 }
167
168 @Override
169 public boolean isReadOverride() {
170 return (readMethod != null && readMethod.isOverride());
171 }
172
173 @Override
174 public boolean isWriteOverride() {
175 return (writeMethod != null && writeMethod.isOverride());
176 }
177
178 @Override
179 public JavaMethod getReadMethod() {
180 return readMethod;
181 }
182
183 @Override
184 public JavaMethod getWriteMethod() {
185 return writeMethod;
186 }
187
188 public ClientType getAs3Type() {
189 return clientType;
190 }
191
192 @Override
193 public ClientType getClientType() {
194 return clientType;
195 }
196
197 @Override
198 public int compareTo(JavaProperty o) {
199 return name.compareTo(o.getName());
200 }
201
202 @Override
203 public boolean equals(Object obj) {
204 if (this == obj)
205 return true;
206 if (obj instanceof JavaMethodProperty)
207 return ((JavaMethodProperty)obj).name.equals(name);
208 return false;
209 }
210
211 @Override
212 public int hashCode() {
213 return name.hashCode();
214 }
215 }