001/* 002 GRANITE DATA SERVICES 003 Copyright (C) 2011 GRANITE DATA SERVICES S.A.S. 004 005 This file is part of Granite Data Services. 006 007 Granite Data Services is free software; you can redistribute it and/or modify 008 it under the terms of the GNU Library General Public License as published by 009 the Free Software Foundation; either version 2 of the License, or (at your 010 option) any later version. 011 012 Granite Data Services is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License 015 for more details. 016 017 You should have received a copy of the GNU Library General Public License 018 along with this library; if not, see <http://www.gnu.org/licenses/>. 019*/ 020 021package org.granite.generator.as3.reflect; 022 023import java.lang.annotation.Annotation; 024import java.lang.reflect.ParameterizedType; 025import java.lang.reflect.Type; 026import java.lang.reflect.TypeVariable; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.List; 030 031import org.granite.generator.as3.ClientType; 032import org.granite.generator.as3.PropertyType; 033import org.granite.messaging.annotations.Include; 034import org.granite.util.ClassUtil; 035 036/** 037 * @author Franck WOLFF 038 */ 039public class JavaMethodProperty implements JavaProperty { 040 041 private final String name; 042 private final JavaMethod readMethod; 043 private final JavaMethod writeMethod; 044 private final Class<?> type; 045 private final Type genericType; 046 private final ClientType clientType; 047 private final boolean externalizedProperty; 048 049 public JavaMethodProperty(JavaTypeFactory provider, String name, JavaMethod readMethod, JavaMethod writeMethod) { 050 this(provider, name, readMethod, writeMethod, null); 051 } 052 053 public JavaMethodProperty(JavaTypeFactory provider, String name, JavaMethod readMethod, JavaMethod writeMethod, ParameterizedType declaringType) { 054 if (name == null || (readMethod == null && writeMethod == null)) 055 throw new NullPointerException("Invalid parameters"); 056 this.name = name; 057 this.readMethod = readMethod; 058 this.writeMethod = writeMethod; 059 Type genericType = ( 060 readMethod != null ? 061 readMethod.getMember().getGenericReturnType() : 062 writeMethod.getMember().getGenericParameterTypes()[0] 063 ); 064 Class<?> declaringClass = readMethod != null ? readMethod.getMember().getDeclaringClass() : writeMethod.getMember().getDeclaringClass(); 065 if (genericType instanceof TypeVariable && declaringType != null) { 066 int index = -1; 067 for (int i = 0; i < declaringClass.getTypeParameters().length; i++) { 068 if (declaringClass.getTypeParameters()[i] == genericType) { 069 index = i; 070 break; 071 } 072 } 073 if (index >= 0 && index < declaringType.getActualTypeArguments().length) 074 genericType = declaringType.getActualTypeArguments()[index]; 075 } 076 this.type = ClassUtil.classOfType(genericType); 077 this.genericType = genericType; 078 ClientType clientType = provider.getClientType(genericType, null, null, isWritable() ? PropertyType.PROPERTY : PropertyType.READONLY_PROPERTY); 079 if (clientType == null) 080 clientType = provider.getAs3Type(type); 081 this.clientType = clientType; 082 this.externalizedProperty = ( 083 readMethod != null && 084 ClassUtil.isAnnotationPresent(readMethod.getMember(), Include.class) 085 ); 086 } 087 088 @Override 089 public String getName() { 090 return name; 091 } 092 093 @Override 094 public String getCapitalizedName() { 095 return getName().substring(0, 1).toUpperCase() + getName().substring(1); 096 } 097 098 @Override 099 public Class<?> getType() { 100 return type; 101 } 102 103 public Type getGenericType() { 104 return genericType; 105 } 106 107 @Override 108 public Type[] getGenericTypes() { 109 Type type = readMethod != null ? readMethod.getMember().getGenericReturnType() : writeMethod.getMember().getGenericParameterTypes()[0]; 110 if (!(type instanceof ParameterizedType)) 111 return null; 112 return ((ParameterizedType)type).getActualTypeArguments(); 113 } 114 115 @Override 116 public boolean isReadable() { 117 return (readMethod != null); 118 } 119 120 @Override 121 public boolean isWritable() { 122 return (writeMethod != null); 123 } 124 125 @Override 126 public boolean isExternalizedProperty() { 127 return externalizedProperty; 128 } 129 130 @Override 131 public boolean isEnum() { 132 return (type.isEnum() || Enum.class.getName().equals(type.getName())); 133 } 134 135 @Override 136 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 137 return ( 138 (readMethod != null && readMethod.getMember().isAnnotationPresent(annotationClass)) || 139 (writeMethod != null && writeMethod.getMember().isAnnotationPresent(annotationClass)) 140 ); 141 } 142 143 @Override 144 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 145 T annotation = null; 146 if (readMethod != null) { 147 annotation = readMethod.getMember().getAnnotation(annotationClass); 148 if (annotation != null) 149 return annotation; 150 } 151 if (writeMethod != null) { 152 annotation = writeMethod.getMember().getAnnotation(annotationClass); 153 if (annotation != null) 154 return annotation; 155 } 156 return null; 157 } 158 159 @Override 160 public Annotation[] getDeclaredAnnotations() { 161 List<Annotation> annos = new ArrayList<Annotation>(); 162 if (readMethod != null) 163 annos.addAll(Arrays.asList(readMethod.getMember().getDeclaredAnnotations())); 164 if (writeMethod != null) 165 annos.addAll(Arrays.asList(writeMethod.getMember().getDeclaredAnnotations())); 166 return annos.toArray(new Annotation[0]); 167 } 168 169 @Override 170 public boolean isReadOverride() { 171 return (readMethod != null && readMethod.isOverride()); 172 } 173 174 @Override 175 public boolean isWriteOverride() { 176 return (writeMethod != null && writeMethod.isOverride()); 177 } 178 179 @Override 180 public JavaMethod getReadMethod() { 181 return readMethod; 182 } 183 184 @Override 185 public JavaMethod getWriteMethod() { 186 return writeMethod; 187 } 188 189 public ClientType getAs3Type() { 190 return clientType; 191 } 192 193 @Override 194 public ClientType getClientType() { 195 return clientType; 196 } 197 198 @Override 199 public int compareTo(JavaProperty o) { 200 return name.compareTo(o.getName()); 201 } 202 203 @Override 204 public boolean equals(Object obj) { 205 if (this == obj) 206 return true; 207 if (obj instanceof JavaMethodProperty) 208 return ((JavaMethodProperty)obj).name.equals(name); 209 return false; 210 } 211 212 @Override 213 public int hashCode() { 214 return name.hashCode(); 215 } 216}