/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.validation;
import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.geotools.validation.dto.ArgumentDTO;
import org.geotools.validation.xml.ValidationException;
/**
* Contains the information required for Validation creation.
*
* <p>
* Currently just used for configuration, may need to be public for dynamic
* configuration.
* </p>
*
* @see <a http://vwfs.refractions.net/docs/Validating_Web_Feature_Server.pdf>A
* PDF on Validating Web Feature Servers</a>
* @source $URL$
*/
public class PlugIn {
Map defaults;
String plugInName;
String plugInDescription;
BeanInfo beanInfo;
Map propertyMap;
PlugIn(Map config) throws ValidationException {
this(get(config, "name"), get(config, "bean", Validation.class),
get(config, "description"), config);
}
public PlugIn(String name, Class type, String description, Map config)
throws ValidationException {
if ((type == null)
|| (!Validation.class.isAssignableFrom(type)
&& type.isInterface())) {
throw new ValidationException("Not a validation test '" + name
+ "' plugIn:" + type);
}
try {
beanInfo = Introspector.getBeanInfo(type);
} catch (Exception e) {
e.printStackTrace();
throw new ValidationException("Could not use the '" + name
+ "' plugIn:" + type.getName());
}
if (config != null) {
defaults = transArgs(config);
}
plugInName = name;
plugInDescription = description;
propertyMap = propertyMap(beanInfo);
}
private Map transArgs(Map config) {
Map defaults = new HashMap();
Iterator i = config.keySet().iterator();
while (i.hasNext()) {
String key = (String) i.next();
Object o = config.get(key);
if (o instanceof ArgumentDTO) {
defaults.put(key, ((ArgumentDTO) o).getValue());
} else {
defaults.put(key, o);
}
}
return defaults;
}
protected PropertyDescriptor propertyInfo(String name) {
return (PropertyDescriptor) propertyMap.get(name);
}
protected static Map propertyMap(BeanInfo info) {
PropertyDescriptor[] properties = info.getPropertyDescriptors();
Map lookup = new HashMap(properties.length);
for (int i = 0; i < properties.length; i++) {
lookup.put(properties[i].getName(), properties[i]);
}
return lookup;
}
/**
* Create a Validation based on provided <code>test</code> definition.
*
* <p>
* Creates the required Java Bean and configures according to the provided
* test definition, using this plugIn's defaults.
* </p>
*
* @param name Map defining User's test.
* @param description DOCUMENT ME!
* @param args DOCUMENT ME!
*
* @return Validation ready for use by the ValidationProcessor
*
* @throws ValidationException when an error occurs
*/
public Validation createValidation(String name, String description, Map args)
throws ValidationException {
BeanDescriptor beanDescriptor = beanInfo.getBeanDescriptor();
Class type = beanDescriptor.getBeanClass();
Constructor create;
try {
create = type.getConstructor(new Class[0]);
} catch (SecurityException e) {
throw new ValidationException("Could not create '" + plugInName
+ "' as " + type.getName(), e);
} catch (NoSuchMethodException e) {
throw new ValidationException("Could not create '" + plugInName
+ "' as " + type.getName(), e);
} catch (IllegalArgumentException e) {
throw new ValidationException("Could not create '" + plugInName
+ "' as " + type.getName(), e);
}
Validation validate;
try {
validate = (Validation) create.newInstance(new Object[0]);
} catch (InstantiationException e) {
throw new ValidationException("Could not create '" + name
+ "' as plugIn " + plugInName, e);
} catch (IllegalAccessException e) {
throw new ValidationException("Could not create '" + name
+ "' as plugIn " + plugInName, e);
} catch (InvocationTargetException e) {
throw new ValidationException("Could not create '" + name
+ "' as plugIn " + plugInName, e);
}
validate.setName(name);
validate.setDescription(description);
configure(validate, defaults);
configure(validate, transArgs(args));
return validate;
}
protected void configure(Object bean, Map config)
throws ValidationException {
if ((config == null) || (config.size() == 0)) {
return;
}
PropertyDescriptor property;
for (Iterator i = config.entrySet().iterator(); i.hasNext();) {
Map.Entry entry = (Map.Entry) i.next();
property = propertyInfo((String) entry.getKey());
if (property == null) {
// error here
continue;
}
try {
property.getWriteMethod().invoke(bean,
new Object[] { entry.getValue() });
} catch (IllegalArgumentException e) {
String val = entry.getValue() == null? entry.getValue().toString():"null";
throw new ValidationException("test failed to configure "
+ plugInName + " " + entry.getKey()+ " "+val, e);
} catch (IllegalAccessException e) {
String val = entry.getValue() == null? entry.getValue().toString():"null";
throw new ValidationException("test failed to configure "
+ plugInName + " " + entry.getKey()+ " "+val, e);
} catch (InvocationTargetException e) {
String val = entry.getValue() == null? entry.getValue().toString():"null";
throw new ValidationException("test failed to configure "
+ plugInName + " " + entry.getKey()+ " "+val, e);
}
}
}
/**
* get purpose.
*
* <p>
* Gets a String from a map of Strings
* </p>
*
* @param map Map the map to extract the string from
* @param key String the key for the map.
*
* @return String the value in the map.
*
* @see Map
*/
private static String get(Map map, String key) {
if (map.containsKey(key)) {
return (String) map.get(key);
}
return null;
}
/**
* get purpose.
*
* <p>
* Gets a Class from a map given the specified key. If the Class is not
* found the default Class is returned.
* </p>
*
* @param map Map the map to extract the file from
* @param key String the key to extract the value for
* @param defaultType The default value should the key not exist.
*
* @return Class an boolean as described above.
*/
private static Class get(Map map, String key, Class defaultType) {
if (!map.containsKey(key)) {
return defaultType;
}
Object value = map.get(key);
if (value instanceof Class) {
return (Class) value;
}
if (value instanceof String) {
try {
return Class.forName((String) value);
} catch (ClassNotFoundException e) {
// error
}
}
return defaultType;
}
public Map getPropertyMap() {
return propertyMap;
}
}