/**
* GRANITE DATA SERVICES
* Copyright (C) 2006-2015 GRANITE DATA SERVICES S.A.S.
*
* This file is part of the Granite Data Services Platform.
*
* Granite Data Services is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* Granite Data Services is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA, or see <http://www.gnu.org/licenses/>.
*/
package org.granite.generator.as3.reflect;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.granite.generator.as3.ClientType;
import org.granite.generator.as3.PropertyType;
/**
* @author Franck WOLFF
*/
public class JavaFieldProperty extends JavaMember<Field> implements JavaProperty {
private final JavaMethod readMethod;
private final JavaMethod writeMethod;
private final JavaTypeFactory provider;
private final ParameterizedType declaringType;
public JavaFieldProperty(JavaTypeFactory provider, Field field, JavaMethod readMethod, JavaMethod writeMethod) {
this(provider, field, readMethod, writeMethod, null);
}
public JavaFieldProperty(JavaTypeFactory provider, Field field, JavaMethod readMethod, JavaMethod writeMethod, ParameterizedType declaringType) {
super(field);
this.provider = provider;
this.readMethod = readMethod;
this.writeMethod = writeMethod;
this.declaringType = declaringType;
}
@Override
public String getCapitalizedName() {
return getName().substring(0, 1).toUpperCase() + getName().substring(1);
}
@Override
public Class<?> getType() {
Type type = getMember().getGenericType();
if (type instanceof TypeVariable && declaringType != null) {
int index = -1;
for (int i = 0; i < getMember().getDeclaringClass().getTypeParameters().length; i++) {
if (getMember().getDeclaringClass().getTypeParameters()[i] == type) {
index = i;
break;
}
}
if (index >= 0 && index < declaringType.getActualTypeArguments().length)
return (Class<?>)declaringType.getActualTypeArguments()[index];
}
return getMember().getType();
}
public Type getGenericType() {
Type type = getMember().getGenericType();
if (type instanceof TypeVariable && declaringType != null) {
int index = -1;
for (int i = 0; i < getMember().getDeclaringClass().getTypeParameters().length; i++) {
if (getMember().getDeclaringClass().getTypeParameters()[i] == type) {
index = i;
break;
}
}
if (index >= 0 && index < declaringType.getActualTypeArguments().length)
return declaringType.getActualTypeArguments()[index];
}
return getMember().getGenericType();
}
@Override
public Type[] getGenericTypes() {
Type type = getMember().getGenericType();
if (!(type instanceof ParameterizedType))
return null;
return ((ParameterizedType)type).getActualTypeArguments();
}
public boolean hasTypePackage() {
return (getTypePackageName().length() > 0);
}
public String getTypePackageName() {
Package p = getType().getPackage();
return (p != null ? p.getName() : "");
}
public String getTypeName() {
return getType().getSimpleName();
}
@Override
public boolean isReadable() {
return (Modifier.isPublic(getMember().getModifiers()) || readMethod != null);
}
@Override
public boolean isWritable() {
return (Modifier.isPublic(getMember().getModifiers()) || writeMethod != null);
}
@Override
public boolean isExternalizedProperty() {
return false;
}
@Override
public boolean isEnum() {
Class<?> type = getType();
return (type.isEnum() || Enum.class.getName().equals(type.getName()));
}
@Override
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
return (
(getMember().isAnnotationPresent(annotationClass)) ||
(readMethod != null && readMethod.getMember().isAnnotationPresent(annotationClass)) ||
(writeMethod != null && writeMethod.getMember().isAnnotationPresent(annotationClass))
);
}
@Override
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
T annotation = getMember().getAnnotation(annotationClass);
if (annotation != null)
return annotation;
if (readMethod != null) {
annotation = readMethod.getMember().getAnnotation(annotationClass);
if (annotation != null)
return annotation;
}
if (writeMethod != null) {
annotation = writeMethod.getMember().getAnnotation(annotationClass);
if (annotation != null)
return annotation;
}
return null;
}
@Override
public Annotation[] getDeclaredAnnotations() {
List<Annotation> annos = new ArrayList<Annotation>(Arrays.asList(getMember().getDeclaredAnnotations()));
if (readMethod != null)
annos.addAll(Arrays.asList(readMethod.getMember().getDeclaredAnnotations()));
if (writeMethod != null)
annos.addAll(Arrays.asList(writeMethod.getMember().getDeclaredAnnotations()));
return annos.toArray(new Annotation[0]);
}
@Override
public boolean isReadOverride() {
return (readMethod != null && readMethod.isOverride());
}
@Override
public boolean isWriteOverride() {
return (writeMethod != null && writeMethod.isOverride());
}
@Override
public JavaMethod getReadMethod() {
return readMethod;
}
@Override
public JavaMethod getWriteMethod() {
return writeMethod;
}
public ClientType getAs3Type() {
ClientType clientType = provider.getClientType(getGenericType(), null, null, isWritable() ? PropertyType.PROPERTY : PropertyType.READONLY_PROPERTY);
if (clientType == null)
return provider.getAs3Type(getType());
return clientType;
}
@Override
public ClientType getClientType() {
return provider.getClientType(getGenericType(), null, null, isWritable() ? PropertyType.PROPERTY : PropertyType.READONLY_PROPERTY);
}
@Override
public int compareTo(JavaProperty o) {
return getName().compareTo(o.getName());
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj instanceof JavaMethodProperty)
return ((JavaMethodProperty)obj).getName().equals(getName());
return false;
}
@Override
public int hashCode() {
return getName().hashCode();
}
@Override
public String toString() {
return getClass().getSimpleName() +
" {name=" + getName() +
", readable=" + (readMethod != null) +
", writable=" + (writeMethod != null) + "}";
}
}