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