/* 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.math.BigInteger;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.opengis.ows11.CodeType;
import net.opengis.ows11.Ows11Factory;
import net.opengis.wps10.ComplexDataDescriptionType;
import net.opengis.wps10.DataInputsType;
import net.opengis.wps10.DescribeProcessType;
import net.opengis.wps10.InputDescriptionType;
import net.opengis.wps10.LiteralInputType;
import net.opengis.wps10.LiteralOutputType;
import net.opengis.wps10.OutputDescriptionType;
import net.opengis.wps10.ProcessDescriptionType;
import net.opengis.wps10.ProcessDescriptionsType;
import net.opengis.wps10.ProcessOutputsType;
import net.opengis.wps10.SupportedComplexDataInputType;
import net.opengis.wps10.SupportedComplexDataType;
import net.opengis.wps10.Wps10Factory;
import org.geoserver.ows.Ows11Util;
import org.geoserver.wfs.xml.XSProfile;
import org.geoserver.wps.ppio.ComplexPPIO;
import org.geoserver.wps.ppio.LiteralPPIO;
import org.geoserver.wps.ppio.ProcessParameterIO;
import org.geotools.data.Parameter;
import org.geotools.feature.NameImpl;
import org.geotools.process.ProcessFactory;
import org.geotools.process.Processors;
import org.opengis.feature.type.Name;
import org.springframework.context.ApplicationContext;
/**
* First-call DescribeProcess class
*
* @author Lucas Reed, Refractions Research Inc
* @author Justin Deoliveira, OpenGEO
*/
public class DescribeProcess {
WPSInfo wps;
ApplicationContext context;
Locale locale;
XSProfile xsp;
Wps10Factory wpsf = Wps10Factory.eINSTANCE;
Ows11Factory owsf = Ows11Factory.eINSTANCE;
public DescribeProcess(WPSInfo wps, ApplicationContext context) {
this.wps = wps;
this.context = context;
locale = Locale.getDefault();
//TODO: creating this ever time this operation is performed is sort of silly
// some sort of singleton would be nice
xsp = new XSProfile();
}
public ProcessDescriptionsType run(DescribeProcessType request) {
ProcessDescriptionsType pds = wpsf.createProcessDescriptionsType();
for ( Iterator i = request.getIdentifier().iterator(); i.hasNext(); ) {
CodeType id = (CodeType) i.next();
processDescription( id, pds );
}
return pds;
}
void processDescription( CodeType id, ProcessDescriptionsType pds ) {
Name name = Ows11Util.name(id);
ProcessFactory pf = Processors.createProcessFactory(name);
if ( pf == null ) {
throw new WPSException( "No such process: " + id.getValue() );
}
ProcessDescriptionType pd = wpsf.createProcessDescriptionType();
pds.getProcessDescription().add( pd );
pd.setProcessVersion( "1.0.0" );
pd.setIdentifier( Ows11Util.code( id.getValue() ) );
pd.setTitle( Ows11Util.languageString(pf.getTitle(name)) );
pd.setAbstract( Ows11Util.languageString(pf.getDescription(name)) );
//data inputs
DataInputsType inputs = wpsf.createDataInputsType();
pd.setDataInputs(inputs);
dataInputs( inputs, pf, name );
//process outputs
ProcessOutputsType outputs = wpsf.createProcessOutputsType();
pd.setProcessOutputs( outputs );
processOutputs( outputs, pf, name );
}
void dataInputs( DataInputsType inputs, ProcessFactory pf, Name name) {
for(Parameter<?> p : pf.getParameterInfo(name).values()) {
InputDescriptionType input = wpsf.createInputDescriptionType();
inputs.getInput().add( input );
input.setIdentifier( Ows11Util.code( p.key ) );
input.setTitle( Ows11Util.languageString( p.title ) );
input.setAbstract( Ows11Util.languageString( p.description ) );
// WPS spec specifies non-negative for unlimited inputs, so -1 -> 0
input.setMaxOccurs( p.maxOccurs == -1
? BigInteger.valueOf( Long.MAX_VALUE ) : BigInteger.valueOf( p.maxOccurs ) );
input.setMinOccurs( BigInteger.valueOf( p.minOccurs ) );
List<ProcessParameterIO> ppios = ProcessParameterIO.findAll( p, context);
if ( ppios.isEmpty() ) {
throw new WPSException( "Could not find process parameter for type " + p.key + "," + p.type );
}
//handle the literal case
if ( ppios.size() == 1 && ppios.get( 0 ) instanceof LiteralPPIO ) {
LiteralPPIO lppio = (LiteralPPIO) ppios.get( 0 );
LiteralInputType literal = wpsf.createLiteralInputType();
input.setLiteralData( literal );
//map the java class to an xml type name
if ( !String.class.equals( lppio.getType() ) ) {
Name typeName = xsp.name( lppio.getType() );
if ( typeName != null ) {
literal.setDataType( Ows11Util.type( typeName.getLocalPart() ) );
}
}
literal.setAnyValue( owsf.createAnyValueType() );
//TODO: output the default value
}
else {
//handle the complex data case
SupportedComplexDataInputType complex = wpsf.createSupportedComplexDataInputType();
input.setComplexData( complex );
complex.setSupported( wpsf.createComplexDataCombinationsType() );
for ( ProcessParameterIO ppio : ppios ) {
ComplexPPIO cppio = (ComplexPPIO) ppio;
ComplexDataDescriptionType format = wpsf.createComplexDataDescriptionType();
format.setMimeType( cppio.getMimeType() );
//add to supported
complex.getSupported().getFormat().add( format );
//handle the default
if ( complex.getDefault() == null ) {
ComplexDataDescriptionType def = wpsf.createComplexDataDescriptionType();
def.setMimeType( format.getMimeType() );
complex.setDefault( wpsf.createComplexDataCombinationType() );
complex.getDefault().setFormat( def );
}
}
}
}
}
void processOutputs( ProcessOutputsType outputs, ProcessFactory pf, Name name) {
Map<String,Parameter<?>> outs = pf.getResultInfo(name, null);
for ( Parameter p : outs.values() ) {
OutputDescriptionType output = wpsf.createOutputDescriptionType();
outputs.getOutput().add( output );
output.setIdentifier( Ows11Util.code( p.key ) );
output.setTitle( Ows11Util.languageString( p.title ) );
List<ProcessParameterIO> ppios = ProcessParameterIO.findAll( p, context);
if ( ppios.isEmpty() ) {
throw new WPSException( "Could not find process parameter for type " + p.key + "," + p.type );
}
//handle the literal case
if ( ppios.size() == 1 && ppios.get( 0 ) instanceof LiteralPPIO ) {
LiteralPPIO lppio = (LiteralPPIO) ppios.get( 0 );
LiteralOutputType literal = wpsf.createLiteralOutputType();
output.setLiteralOutput(literal);
//map the java class to an xml type name
if ( !String.class.equals( lppio.getType() ) ) {
Name typeName = xsp.name( lppio.getType() );
if ( typeName != null ) {
literal.setDataType( Ows11Util.type( typeName.getLocalPart() ) );
}
}
}
else {
//handle the complex data case
SupportedComplexDataType complex = wpsf.createSupportedComplexDataType();
output.setComplexOutput( complex );
complex.setSupported( wpsf.createComplexDataCombinationsType() );
for ( ProcessParameterIO ppio : ppios ) {
ComplexPPIO cppio = (ComplexPPIO) ppio;
ComplexDataDescriptionType format = wpsf.createComplexDataDescriptionType();
format.setMimeType( cppio.getMimeType() );
//add to supported
complex.getSupported().getFormat().add( format );
//handle the default
if ( complex.getDefault() == null ) {
ComplexDataDescriptionType def = wpsf.createComplexDataDescriptionType();
def.setMimeType( format.getMimeType() );
complex.setDefault( wpsf.createComplexDataCombinationType() );
complex.getDefault().setFormat( def );
}
}
}
}
}
}