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 023package org.granite.generator.as3.reflect; 024 025import java.lang.annotation.Annotation; 026import java.lang.reflect.Field; 027import java.lang.reflect.Modifier; 028import java.lang.reflect.ParameterizedType; 029import java.lang.reflect.Type; 030import java.lang.reflect.TypeVariable; 031import java.util.ArrayList; 032import java.util.Arrays; 033import java.util.List; 034 035import org.granite.generator.as3.ClientType; 036import org.granite.generator.as3.PropertyType; 037 038 039/** 040 * @author Franck WOLFF 041 */ 042public 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}