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 */
022package org.granite.messaging.amf.io.util;
023
024import java.lang.annotation.Annotation;
025import java.lang.reflect.Method;
026import java.lang.reflect.Type;
027
028import org.granite.messaging.amf.io.convert.Converters;
029import org.granite.util.TypeUtil;
030import org.granite.util.TypeUtil.DeclaredAnnotation;
031
032/**
033 * @author Franck WOLFF
034 */
035public class MethodProperty extends Property {
036
037    private final Method setter;
038    private final Method getter;
039    private final Type type;
040
041    public MethodProperty(Converters converters, String name, Method setter, Method getter) {
042        super(converters, name);
043        this.setter = setter;
044        this.getter = getter;
045        this.type = getter != null ? getter.getGenericReturnType() : setter.getParameterTypes()[0];
046    }
047
048    @Override
049    public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass, boolean recursive) {
050        if (getter != null) {
051            if (getter.isAnnotationPresent(annotationClass))
052                return true;
053            if (recursive && TypeUtil.isAnnotationPresent(getter, annotationClass))
054                return true;
055        }
056        if (setter != null) {
057            if (setter.isAnnotationPresent(annotationClass))
058                return true;
059            if (recursive && TypeUtil.isAnnotationPresent(setter, annotationClass))
060                return true;
061        }
062        return false;
063    }
064
065    @Override
066        public <T extends Annotation> T getAnnotation(Class<T> annotationClass, boolean recursive) {
067        T annotation = null;
068        if (getter != null) {
069                annotation = getter.getAnnotation(annotationClass);
070                if (annotation == null && recursive) {
071                        DeclaredAnnotation<T> declaredAnnotation = TypeUtil.getAnnotation(getter, annotationClass);
072                        if (declaredAnnotation != null)
073                                annotation = declaredAnnotation.annotation;
074                }
075        }
076        if (annotation == null && setter != null) {
077                annotation = setter.getAnnotation(annotationClass);
078                if (annotation == null && recursive) {
079                        DeclaredAnnotation<T> declaredAnnotation = TypeUtil.getAnnotation(setter, annotationClass);
080                        if (declaredAnnotation != null)
081                                annotation = declaredAnnotation.annotation;
082                }
083        }
084                return annotation;
085        }
086
087        @Override
088    public Type getType() {
089        return type;
090    }
091        
092        @Override
093        public Class<?> getDeclaringClass() {
094                return getter != null ? getter.getDeclaringClass() : setter.getDeclaringClass();
095        }
096
097    @Override
098    public void setProperty(Object instance, Object value, boolean convert) {
099        try {
100            Object[] params = new Object[]{convert ? convert(value) : value};
101            setter.invoke(instance, params);
102        } catch (Exception e) {
103            throw new RuntimeException(e);
104        }
105    }
106
107    @Override
108    public Object getProperty(Object instance) {
109        try {
110            return getter.invoke(instance, new Object[0]);
111        } catch (Throwable e) {
112            throw new RuntimeException(e);
113        }
114    }
115}