001    /*
002      GRANITE DATA SERVICES
003      Copyright (C) 2012 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.client.javafx;
022    
023    import java.lang.annotation.Annotation;
024    import java.lang.reflect.Method;
025    import java.lang.reflect.ParameterizedType;
026    import java.lang.reflect.Type;
027    
028    import javafx.beans.value.ObservableValue;
029    import javafx.beans.value.WritableValue;
030    
031    import org.granite.messaging.amf.io.convert.Converters;
032    import org.granite.messaging.amf.io.util.Property;
033    import org.granite.util.TypeUtil;
034    import org.granite.util.TypeUtil.DeclaredAnnotation;
035    
036    /**
037     * @author William DRAI
038     */
039    public class JavaFXProperty extends Property {
040            
041            private final Method property;
042            private final Method setter;
043            private final Method getter;
044            
045        public JavaFXProperty(Converters converters, String name, Method property, Method getter, Method setter) {
046            super(converters, name);
047            this.property = property;
048            this.setter = setter;
049            this.getter = getter;
050        }
051    
052            @SuppressWarnings("unchecked")
053            @Override
054            public void setProperty(Object instance, Object value, boolean convert) {
055                    Object convertedValue = convert ? convert(value) : value;
056                    try {
057                            ((WritableValue<Object>)property.invoke(instance)).setValue(convertedValue);
058                    } 
059                    catch (Exception e) {
060                            throw new RuntimeException("Could not set value of property " + property, e);
061                    }
062            }
063    
064            @SuppressWarnings("unchecked")
065            @Override
066            public Object getProperty(Object instance) {
067                    try {
068                            return ((ObservableValue<Object>)property.invoke(instance)).getValue();
069                    } 
070                    catch (Exception e) {
071                            throw new RuntimeException("Could not get value of property " + property, e);
072                    }
073            }
074    
075            @Override
076            public Class<?> getDeclaringClass() {
077                    if (getter != null)
078                            return getter.getDeclaringClass();
079                    if (setter != null)
080                            return setter.getDeclaringClass();
081                    
082                    throw new RuntimeException("Could not determine declaring class for property " + getName());
083            }
084    
085            @Override
086            public Type getType() {
087                    if (property.getGenericReturnType() instanceof ParameterizedType && ((ParameterizedType)property.getGenericReturnType()).getActualTypeArguments().length == 1)
088                            return ((ParameterizedType)property.getGenericReturnType()).getActualTypeArguments()[0];
089                    if (getter != null)
090                            return getter.getGenericReturnType();
091                    if (setter != null)
092                            return setter.getGenericParameterTypes()[0];
093                    
094                    throw new RuntimeException("Could not determine property type for property " + getName());
095            }
096    
097            @Override
098            public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass, boolean recursive) {
099                    if (property != null) {
100                if (property.isAnnotationPresent(annotationClass))
101                    return true;
102                if (recursive && TypeUtil.isAnnotationPresent(property, annotationClass))
103                    return true;
104                    }
105            if (getter != null) {
106                if (getter.isAnnotationPresent(annotationClass))
107                    return true;
108                if (recursive && TypeUtil.isAnnotationPresent(getter, annotationClass))
109                    return true;
110            }
111            if (setter != null) {
112                if (setter.isAnnotationPresent(annotationClass))
113                    return true;
114                if (recursive && TypeUtil.isAnnotationPresent(setter, annotationClass))
115                    return true;
116            }
117            return false;
118            }
119    
120            @Override
121            public <T extends Annotation> T getAnnotation(Class<T> annotationClass, boolean recursive) {
122            T annotation = null;
123            if (property != null) {
124                    annotation = property.getAnnotation(annotationClass);
125                    if (annotation == null && recursive) {
126                            DeclaredAnnotation<T> declaredAnnotation = TypeUtil.getAnnotation(property, annotationClass);
127                            if (declaredAnnotation != null)
128                                    annotation = declaredAnnotation.annotation;
129                    }
130            }
131            if (getter != null) {
132                    annotation = getter.getAnnotation(annotationClass);
133                    if (annotation == null && recursive) {
134                            DeclaredAnnotation<T> declaredAnnotation = TypeUtil.getAnnotation(getter, annotationClass);
135                            if (declaredAnnotation != null)
136                                    annotation = declaredAnnotation.annotation;
137                    }
138            }
139            if (annotation == null && setter != null) {
140                    annotation = setter.getAnnotation(annotationClass);
141                    if (annotation == null && recursive) {
142                            DeclaredAnnotation<T> declaredAnnotation = TypeUtil.getAnnotation(setter, annotationClass);
143                            if (declaredAnnotation != null)
144                                    annotation = declaredAnnotation.annotation;
145                    }
146            }
147                    return null;
148            }
149    
150    }