Finally, you complete the Validator so it can retrieve and analyze the information. It will use a handy method for retrieving a PropertyDescriptor from the BeanInfo by the property's programmatic name. In case the property was not found for any reason, the method will notify the caller with a self-explanatory exception.
import java.beans.*;
/**
* This class implements generic data-validation mechanism that is based on the external
* rules defined in the BeanInfo class.
*/
public class Validator implements VetoableChangeListener {
public static final String MAX_VALUE = "maxValue";
public static final String MIN_VALUE = "minValue";
/**
* The only method required by {@link VetoableChangeListener} interface.
*/
public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
try {
// here we hope to retrieve explicitly defined additional information
// about the object-source of the constrained property
BeanInfo info = Introspector.getBeanInfo(evt.getSource().getClass());
// find a property descriptor by given property name
PropertyDescriptor descriptor = getDescriptor(evt.getPropertyName(), info);
Integer max = (Integer) descriptor.getValue(MAX_VALUE);
// check if new value is greater than allowed
if( max != null && max.compareTo(evt.getNewValue()) < 0 ) {
// complain!
throw new PropertyVetoException("Value " + evt.getNewValue() + " is greater than maximum allowed " + max, evt);
}
Integer min = (Integer) descriptor.getValue(MIN_VALUE);
// check if new value is less than allowed
if( min != null && min.compareTo(evt.getNewValue()) > 0 ) {
// complain!
throw new PropertyVetoException("Value " + evt.getNewValue() + " is less than minimum allowed " + min, evt);
}
} catch (IntrospectionException ex) {
ex.printStackTrace();
}
}
/**
* This utility method tries to fetch a PropertyDescriptor from BeanInfo object by given property
* name.
* @param name the programmatic name of the property
* @param info the bean info object that will be searched for the property descriptor.
* @throws IllegalArgumentException if a property with given name does not exist in the given
* BeanInfo object.
*/
private PropertyDescriptor getDescriptor(String name, BeanInfo info) throws IllegalArgumentException {
PropertyDescriptor[] pds = info.getPropertyDescriptors();
for( int i=0; i<pds.length; i++) {
if( pds[i].getName().equals(name) ) {
return pds[i];
}
}
throw new IllegalArgumentException("Property " + name + " not found.");
}
}
Well, believe it or not, that's it! You have all the pieces in place now and are ready to test your data validation. This simple driver does just that:
/**
* A simple application that tries to cause data-validation exception
* condition.
*/
public class Driver {
public static void main(String[] args) {
try {
BusinessObject source = new BusinessObject();
source.setNumericValue(10);
System.out.println("Value accepted: " + source.getNumericValue());
source.setNumericValue(-10);
System.out.println("Value accepted: " + source.getNumericValue());
source.setNumericValue(101);
// we should never reach this line
System.out.println("Value accepted: " + source.getNumericValue());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
No comments:
Post a Comment