/* * Copyright 2006 the original author or authors. * * Licensed 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 org.springmodules.web.propertyeditors; import java.beans.PropertyEditor; import java.beans.PropertyEditorSupport; import java.lang.reflect.Method; import org.springframework.beans.BeanWrapperImpl; /** * {@link java.beans.PropertyEditor} implementation for making instances of generic property editors, capable of converting from text any object type using Java reflection.<br> * Each ReflectivePropertyEditor instance dynamically converts objects to text and vice-versa thanks to four configurable parameters: * <ul> * <li><code>dataAccessObject</code>, the object used for converting from text to the actual desired object: it could be a Factory, or a DAO.</li> * <li><code>dataAccessMethod</code>, the method of the dataAccessObject object to call for converting from text to object.</li> * <li><code>propertyName</code>, the name of the property which will represent the object text value.</li> * <li><code>stringConvertor</code>, for converting the string value to be passed to the <code>dataAccessMethod</code>.</li> * <li><code>stringConvertorOutput</code>, the <code>Class</code> of the object converted by the stringConvertor; if not specified, * the ReflectivePropertyEditor will try to guess it by directly inspecting the converted object.</li> * </ul> * * @author Sergio Bossa */ public class ReflectivePropertyEditor extends PropertyEditorSupport { private Object dataAccessObject; private String dataAccessMethod; private String propertyName; private PropertyEditor stringConvertor; private Class stringConvertorOutput; public String getAsText() { if (this.getValue() == null) { return null; } else { String result = null; try { BeanWrapperImpl wrapper = new BeanWrapperImpl(this.getValue()); result = wrapper.getPropertyValue(this.propertyName).toString(); } catch(Exception ex) { throw new ReflectivePropertyEditorException("An error occurred while getting: " + this.propertyName, ex); } return result; } } public void setAsText(String textValue) { try { if (this.stringConvertor == null) { Method method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{String.class}); this.setValue(method.invoke(this.dataAccessObject, new Object[]{textValue})); } else { this.stringConvertor.setAsText(textValue); Object value = this.stringConvertor.getValue(); Method method = null; if (value == null && this.stringConvertorOutput == null) { throw new ReflectivePropertyEditorException("Cannot convert: " + textValue + ". Unable to determine output class."); } else if (this.stringConvertorOutput != null) { method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{this.stringConvertorOutput}); } else { method = this.dataAccessObject.getClass().getMethod(this.dataAccessMethod, new Class[]{value.getClass()}); } this.setValue(method.invoke(this.dataAccessObject, new Object[]{value})); } } catch(Exception ex) { throw new ReflectivePropertyEditorException("An error occurred while executing: " + this.dataAccessMethod, ex); } } public String getPropertyName() { return this.propertyName; } public void setPropertyName(String propertyName) { this.propertyName = propertyName; } public Object getDataAccessObject() { return this.dataAccessObject; } public void setDataAccessObject(Object dataAccessObject) { this.dataAccessObject = dataAccessObject; } public String getDataAccessMethod() { return this.dataAccessMethod; } public void setDataAccessMethod(String dataAccessMethod) { this.dataAccessMethod = dataAccessMethod; } public PropertyEditor getStringConvertor() { return this.stringConvertor; } public void setStringConvertor(PropertyEditor stringConvertor) { this.stringConvertor = stringConvertor; } public Class getStringConvertorOutput() { return this.stringConvertorOutput; } public void setStringConvertorOutput(Class stringConvertorOutput) { this.stringConvertorOutput = stringConvertorOutput; } }