/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wps;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import net.opengis.ows11.CodeType;
import net.opengis.wps10.DataInputsType1;
import net.opengis.wps10.ExecuteType;
import net.opengis.wps10.InputType;
import org.geoserver.ows.Ows11Util;
import org.geotools.data.Parameter;
import org.geotools.feature.NameImpl;
import org.geotools.process.Process;
import org.geotools.process.ProcessException;
import org.geotools.process.ProcessFactory;
import org.geotools.process.Processors;
import org.opengis.feature.type.Name;
import org.opengis.util.ProgressListener;
/**
* Executes the process defined in an Execute request
*
* @author Lucas Reed, Refractions Research Inc
*/
public class Executor {
private Process process;
private Map<String, Object> inputs;
private ProcessFactory factory;
private Name name;
/**
* Checks and decodes the process inputs from the request
*
* @param request
* @param wps
*/
@SuppressWarnings("unchecked")
public Executor(ExecuteType request, WPSInfo wps) {
CodeType identifier = request.getIdentifier();
this.name = Ows11Util.name(identifier);
this.factory = Processors.createProcessFactory(name);
DataTransformer dataTransformer = new DataTransformer(request.getBaseUrl());
if (null == factory) {
throw new WPSException("InvalidParameterValue", "Identifier");
}
if (false == dataTransformer.isTransmutable(this.factory, name)) {
throw new WPSException("InvalidParameterValue", "Identifier");
}
// Check inputs
Map<String, Parameter<?>> parameterInfo = factory.getParameterInfo(name);
DataInputsType1 requestInputs = request.getDataInputs();
this.checkInputs(parameterInfo, requestInputs);
// Parse inputs
this.inputs = dataTransformer.decodeInputs(request.getDataInputs().getInput(), parameterInfo);
// Get it ready to execute
this.process = factory.create(name);
}
/**
* Returns the ProcessFactory for the Execute request
*
* @return
*/
public ProcessFactory getProcessFactory() {
return this.factory;
}
/**
* Executes process and returns results as Java data types
*
* @return
*/
public Map<String, Object> execute() throws ProcessException {
ProgressListener progress = null;
Map<String, Object> outputs = this.process.execute(this.inputs, progress);
this.checkOutputs(outputs);
return outputs;
}
/**
* Partial output validation
*
* @param outputs
*/
private void checkOutputs(Map<String, Object> outputs) {
Map<String, Parameter<?>> resultInfo = this.factory.getResultInfo(name, null);
for(String key : resultInfo.keySet()) {
if (0 != resultInfo.get(key).minOccurs) {
if (null == outputs || false == outputs.containsKey(key)) {
throw new WPSException("NoApplicableCode", "Process returned null value where one is expected.");
}
}
}
}
/**
* Checks request inputs against those of the requested process implementation
*
* @param processParameters
* @param requestInputs
*/
@SuppressWarnings("unchecked")
private void checkInputs(Map<String, Parameter<?>> processParameters,
DataInputsType1 requestInputs)
{
List<String> requestInputNames = new ArrayList<String>();
List<String> processInputNames = new ArrayList<String>();
processInputNames.addAll(processParameters.keySet());
if (null == requestInputs) {
StringBuffer str = new StringBuffer("");
for(String paramName : processInputNames) {
if (0 == str.length()) {
str.append(paramName);
} else {
str.append(", " + paramName);
}
}
throw new WPSException("MissingParameterValue", str.toString());
}
for(InputType input : (List<InputType>)requestInputs.getInput()) {
requestInputNames.add(input.getIdentifier().getValue());
}
// Check for missing input parameters
for(String processInputName : processInputNames) {
if (false == requestInputNames.contains(processInputName)) {
throw new WPSException("MissingParameterValue", processInputName);
}
}
requestInputNames.removeAll(processInputNames);
// Check for unknown input types
StringBuffer unknownParameters = new StringBuffer("");
for(String unknownName : requestInputNames) {
if (false == "".equals(unknownParameters.toString())) {
unknownParameters.append(", ");
}
unknownParameters.append(unknownName);
}
if (false == "".equals(unknownParameters.toString())) {
throw new WPSException("NoApplicableCode", "Unknown input parameters: " + unknownParameters);
}
return;
}
}