/* GNU GENERAL LICENSE Copyright (C) 2006 The Lobo Project. Copyright (C) 2014 - 2017 Lobo Evolution This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either verion 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General License for more details. You should have received a copy of the GNU General Public along with this program. If not, see <http://www.gnu.org/licenses/>. Contact info: lobochief@users.sourceforge.net; ivan.difrancesco@yahoo.it */ /* * Created on Mar 20, 2005 */ package org.lobobrowser.util; // import java.util.logging.*; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * The Class Bean. * * @author J. H. S. */ public class Bean { // private static final org.apache.logging.log4j.Logger logger = // LogManager.getLogger(Bean.class); /** The clazz. */ private final Class<?> clazz; /** * Instantiates a new bean. * * @param clazz * the clazz */ public Bean(Class<?> clazz) { this.clazz = clazz; } /** The property descriptors. */ private Map<String, PropertyDescriptor> propertyDescriptors = null; /** * Populate descriptors. * * @param map * the map * @param clazz * the clazz * @throws IntrospectionException * the introspection exception */ private void populateDescriptors(Map<String, PropertyDescriptor> map, Class<?> clazz) throws IntrospectionException { BeanInfo beanInfo = Introspector.getBeanInfo(clazz); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (int i = 0; i < pds.length; i++) { map.put(pds[i].getName(), pds[i]); } if (clazz.isInterface()) { java.lang.reflect.Type[] interfaces = clazz.getGenericInterfaces(); for (int i = 0; i < interfaces.length; i++) { this.populateDescriptors(map, (Class<?>) interfaces[i]); } } } /** * Gets the property descriptor. * * @param propertyName * the property name * @return the property descriptor * @throws IntrospectionException * the introspection exception */ public PropertyDescriptor getPropertyDescriptor(String propertyName) throws IntrospectionException { synchronized (this) { if (this.propertyDescriptors == null) { this.propertyDescriptors = new HashMap<String, PropertyDescriptor>(); this.populateDescriptors(this.propertyDescriptors, this.clazz); } return (PropertyDescriptor) this.propertyDescriptors .get(propertyName); } } /** Gets the property descriptors map. * * @return the property descriptors map * @throws IntrospectionException * the introspection exception */ public Map<String, PropertyDescriptor> getPropertyDescriptorsMap() throws IntrospectionException { synchronized (this) { if (this.propertyDescriptors == null) { this.propertyDescriptors = new HashMap<String, PropertyDescriptor>(); this.populateDescriptors(this.propertyDescriptors, this.clazz); } return this.propertyDescriptors; } } /** Gets the property descriptors. * * @return the property descriptors */ public PropertyDescriptor[] getPropertyDescriptors() throws IntrospectionException { synchronized (this) { return (PropertyDescriptor[]) this.getPropertyDescriptorsMap() .values().toArray(new PropertyDescriptor[0]); } } /** * Sets the property for fqn. * * @param receiver * the receiver * @param fullyQualifiedPropertyName * the fully qualified property name * @param value * the value * @throws Exception * the exception */ public void setPropertyForFQN(Object receiver, String fullyQualifiedPropertyName, Object value) throws Exception { int idx = fullyQualifiedPropertyName.indexOf('.'); if (idx == -1) { PropertyDescriptor pd = this .getPropertyDescriptor(fullyQualifiedPropertyName); if (pd == null) { throw new IllegalStateException("Property '" + fullyQualifiedPropertyName + "' unknown"); } Method method = pd.getWriteMethod(); if (method == null) { throw new IllegalStateException("Property '" + fullyQualifiedPropertyName + "' not settable"); } Object actualValue = convertValue(value, pd.getPropertyType()); method.invoke(receiver, new Object[] { actualValue }); } else { String prefix = fullyQualifiedPropertyName.substring(0, idx); PropertyDescriptor pinfo = this.getPropertyDescriptor(prefix); if (pinfo == null) { throw new IllegalStateException( "Property '" + prefix + "' unknown"); } Method readMethod = pinfo.getReadMethod(); if (readMethod == null) { throw new IllegalStateException( "Property '" + prefix + "' not readable"); } Object newReceiver = readMethod.invoke(receiver, new Object[0]); // Class newClass = pinfo.getPropertyType(); String nameRest = fullyQualifiedPropertyName.substring(idx + 1); this.setPropertyForFQN(newReceiver, nameRest, value); } } /** * Convert value. * * @param value * the value * @param targetType * the target type * @return the object */ private static Object convertValue(Object value, Class<?> targetType) { boolean targetString = targetType.isAssignableFrom(String.class); if ((value instanceof String) && targetString) { // ignore } else if (targetString) { value = String.valueOf(value); } else if (!(value instanceof Byte) && ((targetType == Byte.class) || (targetType == byte.class))) { value = Byte.valueOf(String.valueOf(value)); } else if (!(value instanceof Boolean) && ((targetType == Boolean.class) || (targetType == boolean.class))) { value = Boolean.valueOf(String.valueOf(value)); } else if (!(value instanceof Short) && ((targetType == Short.class) || (targetType == short.class))) { value = Short.valueOf(String.valueOf(value)); } else if (!(value instanceof Integer) && ((targetType == Integer.class) || (targetType == int.class))) { value = Integer.valueOf(String.valueOf(value)); } else if (!(value instanceof Long) && ((targetType == Long.class) || (targetType == long.class))) { value = Long.valueOf(String.valueOf(value)); } return value; } }