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