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    package org.granite.util;
023    
024    import java.lang.reflect.Method;
025    
026    
027    public class PropertyDescriptor {
028            
029            private String name;
030        private Method getter;
031        private Method setter;
032    
033        public PropertyDescriptor(String propertyName, Method getter, Method setter) {
034            this.name = propertyName;
035            setReadMethod(getter);
036            setWriteMethod(setter);
037        }
038    
039        public PropertyDescriptor(String propertyName, Class<?> beanClass) {
040            this.name = propertyName;
041            try {
042                setReadMethod(beanClass, createDefaultMethodName(propertyName, "is"));
043            } 
044            catch (Exception e) {
045                setReadMethod(beanClass, createDefaultMethodName(propertyName, "get"));
046            }
047    
048            setWriteMethod(beanClass, createDefaultMethodName(propertyName, "set"));
049        }
050        
051        public String getName() {
052            return this.name;
053        }
054    
055        public void setWriteMethod(Method setter) {
056            this.setter = setter;
057        }
058    
059        public void setReadMethod(Method getter) {
060            this.getter = getter;
061        }
062    
063        public Method getWriteMethod() {
064            return setter;
065        }
066    
067        public Method getReadMethod() {
068            return getter;
069        }
070    
071        @Override
072        public boolean equals(Object object) {
073            if (!(object instanceof PropertyDescriptor))
074                    return false;
075    
076            PropertyDescriptor pd = (PropertyDescriptor)object;
077            if (!((this.getter == null && pd.getter == null) 
078                            || (this.getter != null && this.getter.equals(pd.getter))))
079                    return false;
080            
081            if (!((this.setter == null && pd.setter == null) 
082                            || (this.setter != null && this.setter.equals(pd.setter))))
083                    return false;
084            
085            return this.getPropertyType() == pd.getPropertyType();
086        }
087    
088        @Override
089        public int hashCode() {
090            int hashCode = getter != null ? getter.hashCode() : 0;
091            if (setter != null)
092                    hashCode = hashCode*31 + setter.hashCode();
093            if (getPropertyType() != null)
094                    hashCode = hashCode*31 + getPropertyType().hashCode();
095            return hashCode;
096        }
097    
098        public Class<?> getPropertyType() {
099            if (getter != null)
100                return getter.getReturnType();
101            if (setter != null) {
102                Class<?>[] parameterTypes = setter.getParameterTypes();
103                return parameterTypes[0];
104            }
105            return null;
106        }
107    
108        private String createDefaultMethodName(String propertyName, String prefix) {
109            return prefix + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
110        }
111    
112        private void setReadMethod(Class<?> beanClass, String getterName) {
113            try {
114                Method readMethod = beanClass.getMethod(getterName, new Class[] {});
115                setReadMethod(readMethod);
116            } 
117            catch (Exception e) {
118                throw new RuntimeException("Introspection exception", e);
119            }
120        }
121    
122        private void setWriteMethod(Class<?> beanClass, String setterName) {
123            Method writeMethod = null;
124            try {
125                if (getter != null) {
126                    writeMethod = beanClass.getMethod(setterName, new Class[] { getter.getReturnType() });
127                } 
128                else {
129                    Class<?> clazz = beanClass;
130                    Method[] methods = null;
131                    while (clazz != null && writeMethod == null) {
132                        methods = clazz.getDeclaredMethods();
133                        for (Method method : methods) {
134                            if (setterName.equals(method.getName())) {
135                                if (method.getParameterTypes().length == 1) {
136                                    writeMethod = method;
137                                    break;
138                                }
139                            }
140                        }
141                        clazz = clazz.getSuperclass();
142                    }
143                }
144            } 
145            catch (Exception e) {
146                throw new RuntimeException("Introspection exception", e);
147            }
148            if (writeMethod == null)
149                throw new RuntimeException("Could not find setter for property " + name);
150            
151            setWriteMethod(writeMethod);
152        }
153    }