/*
* Copyright (c) 2002-2003 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.provider.bean;
import com.opensymphony.provider.BeanProvider;
import com.opensymphony.provider.ProviderConfigurationException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.StringTokenizer;
/**
* BeanProvider implementation for accessing properties.
*
* Can handle a.b.c.d -> getA().getB().getC().getD().
* Access properties in this order: bean.getA(), bean.isA(), bean.a(), bean.a.
*
* Can also deal with setter methods.
*
* @author <a href="mailto:[email protected]">Joe Walnes</a>
* @version $Revision: 5 $
*/
public class DefaultBeanProvider implements BeanProvider {
//~ Static fields/initializers /////////////////////////////////////////////
private static String GET = "get";
private static String SET = "set";
private static String IS = "is";
//~ Methods ////////////////////////////////////////////////////////////////
public boolean setProperty(Object object, String property, Object value) {
if ((property == null) || (object == null)) {
return false;
}
// Split out property on dots ( "person.name.first" -> "person","name","first" -> getPerson().getName().getFirst() )
StringTokenizer st = new StringTokenizer(property, ".");
if (st.countTokens() == 0) {
return false;
}
// Holder for Object at current depth along chain.
Object current = object;
try {
// Loop through properties in chain.
for (int i = 0; st.hasMoreTokens(); i++) {
String currentPropertyName = st.nextToken();
if (i < st.countTokens()) {
// This is a getter
current = invokeProperty(current, currentPropertyName);
} else {
// Final property in chain, hence setter
try {
// Call setter
Class cls = current.getClass();
PropertyDescriptor pd = new PropertyDescriptor(currentPropertyName, current.getClass());
pd.getWriteMethod().invoke(current, new Object[] {value});
return true;
} catch (Exception e) {
return false;
}
}
}
// Return holder Object
return true;
} catch (NullPointerException e) {
// It is very likely that one of the properties returned null. If so, catch the exception and return null.
return false;
}
}
public Object getProperty(Object object, String property) {
if ((property == null) || (object == null)) {
return null;
}
// Split out property on dots ( "person.name.first" -> "person","name","first" -> getPerson().getName().getFirst() )
StringTokenizer st = new StringTokenizer(property, ".");
if (st.countTokens() == 0) {
return null;
}
// Holder for Object at current depth along chain.
Object result = object;
try {
// Loop through properties in chain.
while (st.hasMoreTokens()) {
String currentPropertyName = st.nextToken();
// Assign to holder the next property in the chain.
result = invokeProperty(result, currentPropertyName);
}
// Return holder Object
return result;
} catch (NullPointerException e) {
// It is very likely that one of the properties returned null. If so, catch the exception and return null.
return null;
}
}
public void destroy() {
}
public void init() throws ProviderConfigurationException {
}
/**
* Convert property name into getProperty name ( "something" -> "getSomething" )
*/
private String createMethodName(String prefix, String propertyName) {
return prefix + propertyName.toUpperCase().charAt(0) + propertyName.substring(1);
}
/**
* Invoke the method/field getter on the Object.
* It tries (in order) obj.getProperty(), obj.isProperty(), obj.property(), obj.property.
*/
private Object invokeProperty(Object obj, String property) {
if ((property == null) || (property.length() == 0)) {
return null; // just in case something silly happens.
}
Class cls = obj.getClass();
Object[] oParams = {};
Class[] cParams = {};
try {
// First try object.getProperty()
Method method = cls.getMethod(createMethodName(GET, property), cParams);
return method.invoke(obj, oParams);
} catch (Exception e1) {
try {
// First try object.isProperty()
Method method = cls.getMethod(createMethodName(IS, property), cParams);
return method.invoke(obj, oParams);
} catch (Exception e2) {
try {
// Now try object.property()
Method method = cls.getMethod(property, cParams);
return method.invoke(obj, oParams);
} catch (Exception e3) {
try {
// Now try object.property()
Field field = cls.getField(property);
return field.get(obj);
} catch (Exception e4) {
// oh well
return null;
}
}
}
}
}
}
|