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