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