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 @Override 091 public String getName() { 092 return name; 093 } 094 095 @Override 096 public String getCapitalizedName() { 097 return getName().substring(0, 1).toUpperCase() + getName().substring(1); 098 } 099 100 @Override 101 public Class<?> getType() { 102 return type; 103 } 104 105 public Type getGenericType() { 106 return genericType; 107 } 108 109 @Override 110 public Type[] getGenericTypes() { 111 Type type = readMethod != null ? readMethod.getMember().getGenericReturnType() : writeMethod.getMember().getGenericParameterTypes()[0]; 112 if (!(type instanceof ParameterizedType)) 113 return null; 114 return ((ParameterizedType)type).getActualTypeArguments(); 115 } 116 117 @Override 118 public boolean isReadable() { 119 return (readMethod != null); 120 } 121 122 @Override 123 public boolean isWritable() { 124 return (writeMethod != null); 125 } 126 127 @Override 128 public boolean isExternalizedProperty() { 129 return externalizedProperty; 130 } 131 132 @Override 133 public boolean isEnum() { 134 return (type.isEnum() || Enum.class.getName().equals(type.getName())); 135 } 136 137 @Override 138 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) { 139 return ( 140 (readMethod != null && readMethod.getMember().isAnnotationPresent(annotationClass)) || 141 (writeMethod != null && writeMethod.getMember().isAnnotationPresent(annotationClass)) 142 ); 143 } 144 145 @Override 146 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 147 T annotation = null; 148 if (readMethod != null) { 149 annotation = readMethod.getMember().getAnnotation(annotationClass); 150 if (annotation != null) 151 return annotation; 152 } 153 if (writeMethod != null) { 154 annotation = writeMethod.getMember().getAnnotation(annotationClass); 155 if (annotation != null) 156 return annotation; 157 } 158 return null; 159 } 160 161 @Override 162 public Annotation[] getDeclaredAnnotations() { 163 List<Annotation> annos = new ArrayList<Annotation>(); 164 if (readMethod != null) 165 annos.addAll(Arrays.asList(readMethod.getMember().getDeclaredAnnotations())); 166 if (writeMethod != null) 167 annos.addAll(Arrays.asList(writeMethod.getMember().getDeclaredAnnotations())); 168 return annos.toArray(new Annotation[0]); 169 } 170 171 @Override 172 public boolean isReadOverride() { 173 return (readMethod != null && readMethod.isOverride()); 174 } 175 176 @Override 177 public boolean isWriteOverride() { 178 return (writeMethod != null && writeMethod.isOverride()); 179 } 180 181 @Override 182 public JavaMethod getReadMethod() { 183 return readMethod; 184 } 185 186 @Override 187 public JavaMethod getWriteMethod() { 188 return writeMethod; 189 } 190 191 public ClientType getAs3Type() { 192 return clientType; 193 } 194 195 @Override 196 public ClientType getClientType() { 197 return clientType; 198 } 199 200 @Override 201 public int compareTo(JavaProperty o) { 202 return name.compareTo(o.getName()); 203 } 204 205 @Override 206 public boolean equals(Object obj) { 207 if (this == obj) 208 return true; 209 if (obj instanceof JavaMethodProperty) 210 return ((JavaMethodProperty)obj).name.equals(name); 211 return false; 212 } 213 214 @Override 215 public int hashCode() { 216 return name.hashCode(); 217 } 218}