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 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 dataObjectType, Collection dataObjects) { return BeanUtils.getPropertyValuesMap((Class)dataObjectType, (Collection)dataObjects, propertyName, propertyType); } }