Java tutorial
/* Copyright (c) 2001 - 2013 OpenPlans - 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.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import net.opengis.ows11.AllowedValuesType; import net.opengis.ows11.CodeType; import net.opengis.ows11.Ows11Factory; import net.opengis.ows11.ValueType; import net.opengis.wps10.CRSsType; import net.opengis.wps10.ComplexDataDescriptionType; import net.opengis.wps10.DataInputsType; import net.opengis.wps10.DefaultType; 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.SupportedCRSsType; 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.BoundingBoxPPIO; import org.geoserver.wps.ppio.ComplexPPIO; import org.geoserver.wps.ppio.LiteralPPIO; import org.geoserver.wps.ppio.ProcessParameterIO; import org.geoserver.wps.ppio.RawDataPPIO; import org.geoserver.wps.process.AbstractRawData; import org.geoserver.wps.process.GeoServerProcessors; import org.geotools.data.Parameter; import org.geotools.process.ProcessFactory; 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 { static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger(DescribeProcess.class); WPSInfo wps; ApplicationContext context; Locale locale; XSProfile xsp; Wps10Factory wpsf = Wps10Factory.eINSTANCE; Ows11Factory owsf = Ows11Factory.eINSTANCE; /** * Maps the primitive types that can still be used in process input/output descriptions to * object wrappers that we can use in process descriptions */ static final Map<Class, Class> PRIMITIVE_TO_WRAPPER; static { PRIMITIVE_TO_WRAPPER = new HashMap<Class, Class>(); PRIMITIVE_TO_WRAPPER.put(byte.class, Byte.class); PRIMITIVE_TO_WRAPPER.put(short.class, Short.class); PRIMITIVE_TO_WRAPPER.put(int.class, Integer.class); PRIMITIVE_TO_WRAPPER.put(long.class, Long.class); PRIMITIVE_TO_WRAPPER.put(float.class, Float.class); PRIMITIVE_TO_WRAPPER.put(double.class, Double.class); PRIMITIVE_TO_WRAPPER.put(boolean.class, Boolean.class); } 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(); pds.setLang("en"); 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 = GeoServerProcessors.createProcessFactory(name); if (pf == null || pf.create(name) == 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))); pd.setStatusSupported(true); pd.setStoreSupported(true); //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) { Collection<String> outputMimeParameters = AbstractRawData.getOutputMimeParameters(name, pf).values(); for (Parameter<?> p : pf.getParameterInfo(name).values()) { // skip the output mime choice params, they will be filled automatically by WPS if (outputMimeParameters.contains(p.key)) { continue; } 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.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())) { Class type = lppio.getType(); if (PRIMITIVE_TO_WRAPPER.containsKey(type)) { type = PRIMITIVE_TO_WRAPPER.get(type); } Name typeName = xsp.name(type); if (typeName != null) { literal.setDataType(Ows11Util.type("xs:" + typeName.getLocalPart())); } } if (p.metadata.get(Parameter.OPTIONS) != null) { List<Object> options = (List<Object>) p.metadata.get(Parameter.OPTIONS); Object[] optionsArray = (Object[]) options.toArray(new Object[options.size()]); addAllowedValues(literal, optionsArray); } else if (lppio.getType().isEnum()) { Object[] enumValues = lppio.getType().getEnumConstants(); addAllowedValues(literal, enumValues); } else { literal.setAnyValue(owsf.createAnyValueType()); } try { if (p.sample != null) { literal.setDefaultValue(lppio.encode(p.sample)); } } catch (Exception e) { LOGGER.log(Level.WARNING, "Failed to fill the default value for input " + p.key + " of process " + name, e); } } else if (ppios.get(0) instanceof BoundingBoxPPIO) { input.setBoundingBoxData(buildSupportedCRSType()); } 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 = null; if (ppio instanceof RawDataPPIO) { String[] mimeTypes = AbstractRawData.getMimeTypes(p); for (String mimeType : mimeTypes) { ComplexDataDescriptionType ddt = wpsf.createComplexDataDescriptionType(); ddt.setMimeType(mimeType); complex.getSupported().getFormat().add(ddt); if (format == null) { format = ddt; } } } else { 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); } } } } } private void addAllowedValues(LiteralInputType literal, Object[] values) { AllowedValuesType allowed = owsf.createAllowedValuesType(); for (Object value : values) { ValueType vt = owsf.createValueType(); vt.setValue(value.toString()); allowed.getValue().add(vt); } literal.setAllowedValues(allowed); } private SupportedCRSsType buildSupportedCRSType() { SupportedCRSsType supportedCRS = wpsf.createSupportedCRSsType(); DefaultType def = wpsf.createDefaultType(); def.setCRS("EPSG:4326"); supportedCRS.setDefault(def); // TODO: redo the bindings, supported crs should contain a list, not a single value CRSsType crss = wpsf.createCRSsType(); crss.setCRS("EPSG:4326"); supportedCRS.setSupported(crss); return supportedCRS; } 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.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())) { Class type = lppio.getType(); if (PRIMITIVE_TO_WRAPPER.containsKey(type)) { type = PRIMITIVE_TO_WRAPPER.get(type); } Name typeName = xsp.name(type); if (typeName != null) { literal.setDataType(Ows11Util.type(typeName.getLocalPart())); } } } else if (ppios.get(0) instanceof BoundingBoxPPIO) { output.setBoundingBoxOutput(buildSupportedCRSType()); } 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 = null; if (ppio instanceof RawDataPPIO) { String[] mimeTypes = AbstractRawData.getMimeTypes(p); for (String mimeType : mimeTypes) { ComplexDataDescriptionType ddt = wpsf.createComplexDataDescriptionType(); ddt.setMimeType(mimeType); complex.getSupported().getFormat().add(ddt); if (format == null) { format = ddt; } } } else { 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); } } } } } }