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