001: /*
002: * Copyright 2004, 2005, 2006 Odysseus Software GmbH
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package de.odysseus.calyxo.base.util;
017:
018: import java.util.Collections;
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import java.beans.BeanInfo;
024: import java.beans.IntrospectionException;
025: import java.beans.Introspector;
026: import java.beans.PropertyDescriptor;
027:
028: import java.lang.reflect.InvocationTargetException;
029: import java.lang.reflect.Method;
030:
031: /**
032: * Property access utility methods.
033: *
034: * @author Christoph Beck
035: */
036: public class PropertyUtils {
037: private static HashMap descriptorCache = new HashMap();
038:
039: /**
040: * Get map with property descriptors for the specified bean class
041: */
042: private static Map getPropertyDescriptors(Class clazz) {
043: HashMap map = (HashMap) descriptorCache.get(clazz);
044: if (map == null) {
045: BeanInfo beanInfo = null;
046: try {
047: beanInfo = Introspector.getBeanInfo(clazz);
048: } catch (IntrospectionException e) {
049: return Collections.EMPTY_MAP;
050: }
051: PropertyDescriptor[] descriptors = beanInfo
052: .getPropertyDescriptors();
053: if (descriptors == null)
054: descriptors = new PropertyDescriptor[0];
055: map = new HashMap(descriptors.length);
056: for (int i = 0; i < descriptors.length; i++)
057: map.put(descriptors[i].getName(), descriptors[i]);
058: descriptorCache.put(clazz, map);
059: }
060: return map;
061: }
062:
063: /**
064: * Get property names of the specified bean class
065: */
066: public static Iterator getPropertyNames(Class clazz) {
067: return getPropertyDescriptors(clazz).keySet().iterator();
068: }
069:
070: /**
071: * Get specified property descriptor
072: */
073: public static PropertyDescriptor getPropertyDescriptor(Class clazz,
074: String property) {
075: return (PropertyDescriptor) getPropertyDescriptors(clazz).get(
076: property);
077: }
078:
079: /**
080: * Get specified property value
081: */
082: public static Object getProperty(Object bean, String property)
083: throws NoSuchMethodException, IllegalAccessException,
084: InvocationTargetException {
085: PropertyDescriptor descriptor = getPropertyDescriptor(bean
086: .getClass(), property);
087: if (descriptor == null)
088: throw new NoSuchMethodException("Cannot find property "
089: + bean.getClass().getName() + "." + property);
090: Method method = descriptor.getReadMethod();
091: if (method == null)
092: throw new NoSuchMethodException("Cannot find getter for "
093: + bean.getClass().getName() + "." + property);
094: return method.invoke(bean, null);
095: }
096:
097: /**
098: * Get specified nested property value
099: */
100: public static Object getNestedProperty(Object bean, String property)
101: throws NoSuchMethodException, IllegalAccessException,
102: InvocationTargetException {
103: if (property.indexOf('.') > 0) {
104: String[] path = property.split("\\.");
105: for (int i = 0; i < path.length && bean != null; i++) {
106: bean = getProperty(bean, path[i]);
107: }
108: return bean;
109: } else {
110: return getProperty(bean, property);
111: }
112: }
113:
114: /**
115: * Set specified property value
116: */
117: public static void setProperty(Object bean, String property,
118: Object value) throws NoSuchMethodException,
119: IllegalAccessException, InvocationTargetException {
120: PropertyDescriptor descriptor = getPropertyDescriptor(bean
121: .getClass(), property);
122: if (descriptor == null)
123: throw new NoSuchMethodException("Cannot find property "
124: + bean.getClass().getName() + "." + property);
125: Method method = descriptor.getWriteMethod();
126: if (method == null)
127: throw new NoSuchMethodException("Cannot find setter for "
128: + bean.getClass().getName() + "." + property);
129: method.invoke(bean, new Object[] { value });
130: }
131:
132: /**
133: * Set nested property given by property path, starting at specified
134: * index. Dynamically create beans if necessary. Take care not to
135: * leave the bean changed if an exception occurs.
136: */
137: private static void setNestedPropertyWithCreate(Object bean,
138: String[] path, int start, Object value)
139: throws NoSuchMethodException, IllegalAccessException,
140: InvocationTargetException, InstantiationException {
141: for (int i = start; i < path.length - 1; i++) {
142: Object object = getProperty(bean, path[i]);
143: if (object == null) {
144: PropertyDescriptor descr = getPropertyDescriptor(bean
145: .getClass(), path[i]);
146: object = descr.getPropertyType().newInstance();
147: setNestedPropertyWithCreate(object, path, i + 1, value);
148: setProperty(bean, path[i], object);
149: return;
150: }
151: bean = object;
152: }
153: setProperty(bean, path[path.length - 1], value);
154: }
155:
156: /**
157: * Set specified nested property value
158: */
159: public static void setNestedProperty(Object bean, String property,
160: Object value) throws NoSuchMethodException,
161: IllegalAccessException, InvocationTargetException,
162: InstantiationException {
163: int lastDot = property.lastIndexOf('.');
164: if (lastDot > 0) {
165: setNestedPropertyWithCreate(bean, property.split("\\."), 0,
166: value);
167: } else {
168: setProperty(bean, property, value);
169: }
170: }
171:
172: /**
173: * Set specified property value from string
174: */
175: public static void setPropertyFromString(Object bean,
176: String property, String string) throws Exception {
177: PropertyDescriptor descriptor = getPropertyDescriptor(bean
178: .getClass(), property);
179: if (descriptor == null)
180: throw new NoSuchMethodException("Cannot find property "
181: + bean.getClass().getName() + "." + property);
182: Method method = descriptor.getWriteMethod();
183: if (method == null)
184: throw new NoSuchMethodException("Cannot find setter for "
185: + bean.getClass().getName() + "." + property);
186: Object value = ParseUtils.parse(descriptor.getPropertyType(),
187: string);
188: method.invoke(bean, new Object[] { value });
189: }
190:
191: }
|