/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.beans; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import org.apache.harmony.beans.BeansUtils; /** * Describes one Java Bean property. * * NOTE: PropertyEditor support is not available in j2objc, since it depends * on core AWT classes. */ public class PropertyDescriptor extends FeatureDescriptor { private Method getter; private Method setter; // private Class<?> propertyEditorClass; boolean constrained; boolean bound; public PropertyDescriptor(String propertyName, Class<?> beanClass, String getterName, String setterName) throws IntrospectionException { super(); if (beanClass == null) { throw new IntrospectionException("Target Bean class is null"); } if (propertyName == null || propertyName.length() == 0) { throw new IntrospectionException("bad property name"); } this.setName(propertyName); if (getterName != null) { if (getterName.length() == 0) { throw new IntrospectionException( "read or write method cannot be empty."); } try { setReadMethod(beanClass, getterName); } catch (IntrospectionException e) { setReadMethod(beanClass, createDefaultMethodName(propertyName, "get")); } } if (setterName != null) { if (setterName.length() == 0) { throw new IntrospectionException( "read or write method cannot be empty."); } setWriteMethod(beanClass, setterName); } } public PropertyDescriptor(String propertyName, Method getter, Method setter) throws IntrospectionException { super(); if (propertyName == null || propertyName.length() == 0) { throw new IntrospectionException("bad property name"); } this.setName(propertyName); setReadMethod(getter); setWriteMethod(setter); } public PropertyDescriptor(String propertyName, Class<?> beanClass) throws IntrospectionException { if (beanClass == null) { throw new IntrospectionException("Target Bean class is null"); } if (propertyName == null || propertyName.length() == 0) { throw new IntrospectionException("bad property name"); } this.setName(propertyName); try { setReadMethod(beanClass, createDefaultMethodName(propertyName, "is")); } catch (Exception e) { setReadMethod(beanClass, createDefaultMethodName(propertyName, "get")); //$NON-NLS-1$ } setWriteMethod(beanClass, createDefaultMethodName(propertyName, "set")); } public void setWriteMethod(Method setter) throws IntrospectionException { if (setter != null) { int modifiers = setter.getModifiers(); if (!Modifier.isPublic(modifiers)) { throw new IntrospectionException("Modifier for setter method should be public."); } Class<?>[] parameterTypes = setter.getParameterTypes(); if (parameterTypes.length != 1) { throw new IntrospectionException( "Number of parameters in setter method is not equal to 1."); } Class<?> parameterType = parameterTypes[0]; Class<?> propertyType = getPropertyType(); if (propertyType != null && !propertyType.equals(parameterType)) { throw new IntrospectionException( "Parameter type in setter method does not corresponds to predefined."); } } this.setter = setter; } public void setReadMethod(Method getter) throws IntrospectionException { if (getter != null) { int modifiers = getter.getModifiers(); if (!Modifier.isPublic(modifiers)) { throw new IntrospectionException("Modifier for getter method should be public."); } Class<?>[] parameterTypes = getter.getParameterTypes(); if (parameterTypes.length != 0) { throw new IntrospectionException( "Number of parameters in getter method is not equal to 0."); } Class<?> returnType = getter.getReturnType(); if (returnType.equals(Void.TYPE)) { throw new IntrospectionException("getter cannot return <void>"); } Class<?> propertyType = getPropertyType(); if ((propertyType != null) && !returnType.equals(propertyType)) { throw new IntrospectionException( "Parameter type in getter method does not corresponds to predefined."); } } this.getter = getter; } public Method getWriteMethod() { return setter; } public Method getReadMethod() { return getter; } @Override public boolean equals(Object object) { boolean result = object instanceof PropertyDescriptor; if (result) { PropertyDescriptor pd = (PropertyDescriptor) object; boolean gettersAreEqual = (this.getter == null) && (pd.getReadMethod() == null) || (this.getter != null) && (this.getter.equals(pd.getReadMethod())); boolean settersAreEqual = (this.setter == null) && (pd.getWriteMethod() == null) || (this.setter != null) && (this.setter.equals(pd.getWriteMethod())); boolean propertyTypesAreEqual = this.getPropertyType() == pd .getPropertyType(); // boolean propertyEditorClassesAreEqual = this // .getPropertyEditorClass() == pd.getPropertyEditorClass(); boolean boundPropertyAreEqual = this.isBound() == pd.isBound(); boolean constrainedPropertyAreEqual = this.isConstrained() == pd .isConstrained(); result = gettersAreEqual && settersAreEqual // && propertyTypesAreEqual && propertyEditorClassesAreEqual && propertyTypesAreEqual && boundPropertyAreEqual && constrainedPropertyAreEqual; } return result; } @Override public int hashCode() { return BeansUtils.getHashCode(getter) + BeansUtils.getHashCode(setter) + BeansUtils.getHashCode(getPropertyType()) // + BeansUtils.getHashCode(getPropertyEditorClass()) + BeansUtils.getHashCode(isBound()) + BeansUtils.getHashCode(isConstrained()); } // public void setPropertyEditorClass(Class<?> propertyEditorClass) { // this.propertyEditorClass = propertyEditorClass; // } public Class<?> getPropertyType() { Class<?> result = null; if (getter != null) { result = getter.getReturnType(); } else if (setter != null) { Class<?>[] parameterTypes = setter.getParameterTypes(); result = parameterTypes[0]; } return result; } // public Class<?> getPropertyEditorClass() { // return propertyEditorClass; // } public void setConstrained(boolean constrained) { this.constrained = constrained; } public void setBound(boolean bound) { this.bound = bound; } public boolean isConstrained() { return constrained; } public boolean isBound() { return bound; } String createDefaultMethodName(String propertyName, String prefix) { String result = null; if (propertyName != null) { String bos = BeansUtils.toASCIIUpperCase(propertyName.substring(0, 1)); String eos = propertyName.substring(1, propertyName.length()); result = prefix + bos + eos; } return result; } void setReadMethod(Class<?> beanClass, String getterName) throws IntrospectionException { try { Method readMethod = beanClass.getMethod(getterName, new Class[] {}); setReadMethod(readMethod); } catch (Exception e) { throw new IntrospectionException(e.getLocalizedMessage()); } } void setWriteMethod(Class<?> beanClass, String setterName) throws IntrospectionException { Method writeMethod = null; try { if (getter != null) { writeMethod = beanClass.getMethod(setterName, new Class[] { getter.getReturnType() }); } else { Class<?> clazz = beanClass; Method[] methods = null; while (clazz != null && writeMethod == null) { methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (setterName.equals(method.getName())) { if (method.getParameterTypes().length == 1) { writeMethod = method; break; } } } clazz = clazz.getSuperclass(); } } } catch (Exception e) { throw new IntrospectionException(e.getLocalizedMessage()); } if (writeMethod == null) { throw new IntrospectionException("Method not found: " + setterName); } setWriteMethod(writeMethod); } // public PropertyEditor createPropertyEditor(Object bean) { // PropertyEditor editor; // if (propertyEditorClass == null) { // return null; // } // if (!PropertyEditor.class.isAssignableFrom(propertyEditorClass)) { // throw new ClassCastException( // "Property editor is not assignable from the PropertyEditor interface"); // } // try { // Constructor<?> constr; // try { // // try to look for the constructor with single Object argument // constr = propertyEditorClass.getConstructor(Object.class); // editor = (PropertyEditor) constr.newInstance(bean); // } catch (NoSuchMethodException e) { // // try no-argument constructor // constr = propertyEditorClass.getConstructor(); // editor = (PropertyEditor) constr.newInstance(); // } // } catch (Exception e) { // RuntimeException re = new RuntimeException("Unable to instantiate property editor", e); // throw re; // } // return editor; // } }