package com.onaro.sanscreen.client.view.common.functions;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IAdaptable;
import com.onaro.client.leekui.runtime.OnaroAdapterUtils;
import com.onaro.commons.beans.BeanUtils;
import com.onaro.commons.lang.OnaroThreadUtils;
import com.onaro.sanscreen.server.interfaces.data.Context;
import com.onaro.sanscreen.server.interfaces.data.DataObject;
import com.onaro.sanscreen.server.interfaces.data.IDataObjectType;
/**
* Bulk function that will retrieve a bean property from each input element, use the property values
* to evaluate a function call, and correlate the input elements back to the results of the function call.
*
* @param type of the input elements
* @param type of the output of the function
* @param type of the property that will be retrieved from the inputs
*/
public abstract class AbstractPropertyParamBulkFunction extends
AbstractDataObjectTypeAndContextAwareBulkFunction {
protected final String propertyName;
protected final Class propertyType;
/**
* Construct AbstractPropertyParamBulkFunction that will retrieve the given the property off the
* input objects and use them as parameters for evaluation.
*
* @param propertyName the name of the Java Bean property used as a parameter
* @param propertyType the type of the property
*/
public AbstractPropertyParamBulkFunction(String propertyName, Class propertyType) {
super();
this.propertyName = propertyName;
this.propertyType = propertyType;
}
/**
* Construct AbstractPropertyParamBulkFunction that will retrieve the given the property off the
* input objects and use them as parameters for evaluation.
*
* @param propertyName the name of the Java Bean property used as a parameter
* @param propertyType the type of the property
*/
public AbstractPropertyParamBulkFunction(String propertyName, Class propertyType, boolean isMainView) {
super(isMainView);
this.propertyName = propertyName;
this.propertyType = propertyType;
}
/**
* Evaluate the bulk function based on the given property values.
*
* @param properties the property values used for function evaluation
* @param context the context
* @return a map between the property value and the function result
*
* @throws InterruptedException if the evaluation was interrupted
* @throws InvocationTargetException if an error occurred during evaluation
*/
protected abstract Map evaluate(Set properties, Context context)
throws InterruptedException, InvocationTargetException;
@Override
protected void evaluate(Collection inputs, IDataObjectType dataObjectType, Context context,
Map outputMap) throws InterruptedException, InvocationTargetException {
// Get the property values for each input element
Map idsMap = getPropertyValues(dataObjectType, inputs);
OnaroThreadUtils.checkInterrupted();
// Consolidate property values into a set
Set values = new HashSet(idsMap.values());
Map results = evaluate(values, context);
OnaroThreadUtils.checkInterrupted();
// Put the results into the output map
for (Entry entry : idsMap.entrySet()) {
Output result = results.get(entry.getValue());
outputMap.put(entry.getKey(), result);
}
}
/**
* Retrieve the property values to use as a parameter for function evaluation. This method will get the bean property
* value for each input element.
*
* @param the input element type
* @param dataObjectType the data object type of the input elements
* @param inputs the input elements
* @return a mapping from the input element to their property value.
*/
protected Map getPropertyValues(IDataObjectType dataObjectType, Collection inputs) {
Map idsMap = new IdentityHashMap(inputs.size());
// Get the class of the data object
Class extends DataObject> dataObjectClass = dataObjectType.getDataObjectClass();
// Adapt the inputs to their data object class
Map adaptersMap = OnaroAdapterUtils.getAdaptersMap(inputs, dataObjectClass);
// Get the properties off of the data objects
Map valuesMap = getBeanPropertyValuesMap(dataObjectClass, adaptersMap.values());
// Map the property values back to the original inputs
for (I input : inputs) {
DataObject dataObject = adaptersMap.get(input);
Property value = valuesMap.get(dataObject);
idsMap.put(input, value);
}
return idsMap;
}
/**
* Raw (unchecked generics) version of the BeanUtils.getPropertyValuesMap
*
* @param dataObjectType
* @param dataObjects
* @return
*/
@SuppressWarnings("unchecked")
private Map getBeanPropertyValuesMap(Class extends DataObject> dataObjectType, Collection extends DataObject> dataObjects) {
return BeanUtils.getPropertyValuesMap((Class)dataObjectType, (Collection)dataObjects, propertyName, propertyType);
}
}