/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 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.process.impl;
import java.awt.RenderingHints.Key;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.geotools.data.Parameter;
import org.geotools.process.Process;
import org.geotools.process.ProcessFactory;
import org.geotools.text.Text;
import org.opengis.util.InternationalString;
/**
* Reflective implementation of a {@link SingleProcessFactory} that will embed in the
* same entity both the process and the factory.
* The process is supposed to take a bean as a parameter and return a bean as a result.
*
* @source $URL$
*/
public abstract class BeanProcessFactory implements ProcessFactory {
public Process create() {
return new SimpleProcess(this){
public void process() throws Exception {
BeanProcessFactory.this.process( input, result );
}
};
}
public InternationalString getDescription() {
// TODO Auto-generated method stub
return null;
}
public String getName() {
return getClass().getSimpleName();
}
public Map<String, Parameter< ? >> getParameterInfo() {
BeanInfo info;
try {
info = Introspector.getBeanInfo( getInputBean() );
} catch (IntrospectionException e) {
return null;
}
Map<String,Parameter<?>> parameterInfo = new HashMap<String, Parameter<?>>();
for( PropertyDescriptor descriptor : info.getPropertyDescriptors() ){
Method getter = descriptor.getReadMethod();
if( getter == null ) continue;
Parameter<?> parameter = new Parameter(descriptor.getName(), descriptor.getPropertyType(),
Text.text(descriptor.getDisplayName()),
Text.text(descriptor.getShortDescription()) );
parameterInfo.put( descriptor.getName(), parameter );
}
return parameterInfo;
}
public Map<String, Parameter< ? >> getResultInfo() {
BeanInfo info;
try {
info = Introspector.getBeanInfo( getResultBean() );
} catch (IntrospectionException e) {
return null;
}
Map<String,Parameter<?>> parameterInfo = new HashMap<String, Parameter<?>>();
for( PropertyDescriptor descriptor : info.getPropertyDescriptors() ){
Method setter = descriptor.getWriteMethod();
if( setter == null ) continue;
Parameter<?> parameter = new Parameter(descriptor.getName(), descriptor.getPropertyType(),
Text.text(descriptor.getDisplayName()),
Text.text(descriptor.getShortDescription()) );
parameterInfo.put( descriptor.getName(), parameter );
}
return parameterInfo;
}
public Map<String, Parameter< ? >> getResultInfo( Map<String, Object> parameters )
throws IllegalArgumentException {
return null;
}
public InternationalString getTitle() {
return Text.text( getClass().getSimpleName() );
}
protected void process( Map<String, Object> inputMap, Map<String, Object> resultMap ) throws Exception {
BeanInfo inputInfo = Introspector.getBeanInfo( getInputBean() );
Object inputBean = inputInfo.getBeanDescriptor().getBeanClass().getConstructor( new Class[0]);
// should use commons beans here ....
configure( inputInfo, inputMap, inputBean );
Object resultBean = process( inputBean );
BeanInfo resultInfo = Introspector.getBeanInfo( getResultBean(), Object.class );
results( resultMap, resultBean, resultInfo );
}
private void results( Map<String, Object> resultMap, Object bean, BeanInfo info ) {
for( PropertyDescriptor property : info.getPropertyDescriptors() ){
if( resultMap.containsKey( property.getName() )){
Method setter = property.getReadMethod();
try {
Object value = setter.invoke( bean );
resultMap.put( property.getName(), value );
} catch (Exception e) {
// ignore for right now .. TODO WARNING
}
}
}
}
private void configure( BeanInfo info, Map<String, Object> inputMap, Object bean ) {
for( PropertyDescriptor property : info.getPropertyDescriptors() ){
if( inputMap.containsKey( property.getName() )){
Method setter = property.getWriteMethod();
try {
setter.invoke( bean, inputMap.get( property.getName() ));
} catch (Exception e) {
// ignore for right now .. TODO WARNING
}
}
}
}
/**
* Default Implementation return true
*/
public boolean isAvailable() {
return true;
}
/**
* The default implementation returns an empty map.
*/
public Map<Key, ?> getImplementationHints() {
return Collections.emptyMap();
}
/**
* Please return us an instanceof the bean you expect for input.
* <p>
* We will generate the correct process api input parameters to reflect
* your choice.
* @return bean used for input
*/
protected abstract Class<?> getInputBean();
protected abstract Class<?> getResultBean();
protected abstract Object process( Object input );
}