org.geoserver.wps.kvp.ExecuteKvpRequestReader.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.wps.kvp.ExecuteKvpRequestReader.java

Source

/* 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.kvp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.opengis.ows11.BoundingBoxType;
import net.opengis.ows11.Ows11Factory;
import net.opengis.wps10.ComplexDataType;
import net.opengis.wps10.DataInputsType1;
import net.opengis.wps10.DocumentOutputDefinitionType;
import net.opengis.wps10.ExecuteType;
import net.opengis.wps10.InputReferenceType;
import net.opengis.wps10.InputType;
import net.opengis.wps10.LiteralDataType;
import net.opengis.wps10.OutputDefinitionType;
import net.opengis.wps10.ResponseDocumentType;
import net.opengis.wps10.ResponseFormType;
import net.opengis.wps10.Wps10Factory;

import org.geoserver.ows.Ows11Util;
import org.geoserver.ows.kvp.EMFKvpRequestReader;
import org.geoserver.wps.WPSException;
import org.geoserver.wps.ppio.BoundingBoxPPIO;
import org.geoserver.wps.ppio.LiteralPPIO;
import org.geoserver.wps.ppio.ProcessParameterIO;
import org.geoserver.wps.process.GeoServerProcessors;
import org.geotools.data.Parameter;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.gml2.bindings.GML2EncodingUtils;
import org.geotools.process.ProcessFactory;
import org.opengis.feature.type.Name;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ExecuteKvpRequestReader extends EMFKvpRequestReader implements ApplicationContextAware {

    ApplicationContext applicationContext;

    public ExecuteKvpRequestReader() {
        super(ExecuteType.class, Wps10Factory.eINSTANCE);
    }

    @Override
    public Object read(Object request, Map kvp, Map rawKvp) throws Exception {
        ExecuteType execute = (ExecuteType) super.read(request, kvp, rawKvp);
        Wps10Factory factory = Wps10Factory.eINSTANCE;

        // grab the process, we need it to parse the data inputs
        Name processName = Ows11Util.name(execute.getIdentifier());
        ProcessFactory pf = GeoServerProcessors.createProcessFactory(processName);
        if (pf == null) {
            throw new WPSException("No such process: " + processName);
        }

        // parse inputs
        List<InputType> inputs = parseDataInputs(pf.getParameterInfo(processName),
                (String) rawKvp.get("DataInputs"));
        DataInputsType1 input1 = factory.createDataInputsType1();
        input1.getInput().addAll(inputs);
        execute.setDataInputs(input1);

        if (rawKvp.containsKey("responseDocument")) {
            execute.setResponseForm(parseResponseDocument(pf.getResultInfo(processName, null),
                    (String) rawKvp.get("responseDocument")));
        } else if (rawKvp.containsKey("rawDataOutput")) {
            execute.setResponseForm(
                    parseRawDataOutput(pf.getResultInfo(processName, null), (String) rawKvp.get("rawDataOutput")));
        } else {
            ResponseFormType responseForm = factory.createResponseFormType();
            responseForm.setResponseDocument(factory.createResponseDocumentType());
            execute.setResponseForm(responseForm);
        }

        if ("true".equals(kvp.get("storeExecuteResponse"))) {
            if (execute.getResponseForm().getResponseDocument() == null) {
                throw new WPSException("InvalidParameterValue", "Cannot store the response for raw data outputs, "
                        + "please use response document instead");
            }
            execute.getResponseForm().getResponseDocument().setStoreExecuteResponse(true);
        }

        if ("true".equals(kvp.get("lineage"))) {
            if (execute.getResponseForm().getResponseDocument() == null) {
                throw new WPSException("InvalidParameterValue",
                        "Cannot provide lineage in the response for raw data outputs, "
                                + "please use response document instead");
            }
            execute.getResponseForm().getResponseDocument().setLineage(true);
        }

        if ("true".equals(kvp.get("status"))) {
            if (execute.getResponseForm().getResponseDocument() == null) {
                throw new WPSException("InvalidParameterValue", "Cannot add status with raw data outputs, "
                        + "please use response document with store option instead");
            }
            if (!execute.getResponseForm().getResponseDocument().isStoreExecuteResponse()) {
                throw new WPSException("InvalidParameterValue", "Cannot add status if the response "
                        + "is not stored, please add storeExecuteResponse=true your request");
            }
            execute.getResponseForm().getResponseDocument().setStatus(true);
        }

        return execute;
    }

    protected boolean filter(String kvp) {
        return "DataInputs".equalsIgnoreCase(kvp) || "responseDocument".equalsIgnoreCase(kvp)
                || "rawDataOutput".equalsIgnoreCase(kvp);
    };

    List<InputType> parseDataInputs(Map<String, Parameter<?>> inputParams, String inputString) {
        List<IOParam> params = parseIOParameters(inputString);

        List<InputType> result = new ArrayList<InputType>();
        for (IOParam ioParam : params) {
            // common
            Wps10Factory factory = Wps10Factory.eINSTANCE;
            InputType it = factory.createInputType();
            it.setIdentifier(Ows11Util.code(ioParam.id));
            it.setData(factory.createDataType());

            Parameter<?> gtParam = inputParams.get(ioParam.id);
            if (gtParam == null) {
                throw new WPSException("Unknown data input named '" + ioParam.id + "'");
            }
            ProcessParameterIO ppio = ProcessParameterIO.findAll(gtParam, applicationContext).get(0);

            if (ppio instanceof LiteralPPIO) {
                it.getData().setLiteralData(parseLiteral(it, factory, ioParam));
            } else if (ppio instanceof BoundingBoxPPIO) {
                it.getData().setBoundingBoxData(parseBoundingBox(it, factory, ioParam));
            } else if (ioParam.isReference()) {
                it.setReference(parseReferenceType(it, factory, ioParam));
            } else {
                it.getData().setComplexData(parseComplex(it, factory, ioParam));
            }

            result.add(it);
        }

        return result;
    }

    /**
     * Parses a list of a I/O parameters
     * @param inputString
     * @return
     */
    List<IOParam> parseIOParameters(String inputString) {
        List<IOParam> result = new ArrayList<IOParam>();

        if (inputString == null || "".equals(inputString.trim())) {
            return Collections.emptyList();
        }

        // inputs are separated by ;
        String[] inputs = inputString.split(";");

        for (String input : inputs) {
            // separate the id form the value/attribute
            int idx = input.indexOf("=");
            if (idx == -1) {
                result.add(new IOParam(input, null, Collections.EMPTY_MAP));
            } else {
                String inputId = input.substring(0, idx);
                String[] valueAttributes = input.substring(idx + 1, input.length()).split("@");

                String value = valueAttributes[0];
                Map<String, String> attributes = parseAttributes(valueAttributes);

                result.add(new IOParam(inputId, value, attributes));
            }
        }

        return result;
    }

    Map<String, String> parseAttributes(String[] attributes) {
        Map<String, String> result = new HashMap<String, String>();

        // start from 1, 0 is the value
        for (int i = 1; i < attributes.length; i++) {
            final String att = attributes[i];
            int idx = att.indexOf("=");
            if (idx == -1) {
                throw new WPSException("Invalid syntax for data input attribute: @" + att);
            }
            if (idx == att.length() - 1) {
                result.put(att.substring(0, idx), null);
            } else {
                result.put(att.substring(0, idx), att.substring(idx + 1, att.length()));
            }

        }

        return result;
    }

    private InputReferenceType parseReferenceType(InputType it, Wps10Factory factory, IOParam param) {
        InputReferenceType ref = factory.createInputReferenceType();
        if (param.attributes.containsKey("href")) {
            ref.setHref(param.attributes.get("href"));
        } else {
            ref.setHref(param.attributes.get("xlink:href"));
        }
        ref.setEncoding(param.attributes.get("encoding"));
        ref.setMimeType(param.attributes.get("mimetype"));
        ref.setSchema(param.attributes.get("schema"));

        return ref;
    }

    private ComplexDataType parseComplex(InputType it, Wps10Factory factory, IOParam param) {
        ComplexDataType complex = factory.createComplexDataType();
        complex.getData().add(param.value);
        complex.setEncoding(param.attributes.get("encoding"));
        complex.setMimeType(param.attributes.get("mimetype"));
        complex.setSchema(param.attributes.get("schema"));

        return complex;
    }

    private BoundingBoxType parseBoundingBox(InputType it, Wps10Factory factory, IOParam param) {
        try {
            ReferencedEnvelope envelope = (ReferencedEnvelope) new org.geoserver.wfs.kvp.BBoxKvpParser()
                    .parse(param.value);
            if (envelope != null) {
                BoundingBoxType bbox = Ows11Factory.eINSTANCE.createBoundingBoxType();
                if (envelope.getCoordinateReferenceSystem() != null) {
                    bbox.setCrs(GML2EncodingUtils.epsgCode(envelope.getCoordinateReferenceSystem()));
                }
                List<Double> min = new ArrayList<Double>(envelope.getDimension());
                List<Double> max = new ArrayList<Double>(envelope.getDimension());
                for (int i = 0; i < envelope.getDimension(); i++) {
                    min.set(i, envelope.getMinimum(i));
                    max.set(i, envelope.getMaximum(i));
                }

                return bbox;
            } else {
                return null;
            }
        } catch (Exception e) {
            throw new WPSException("Failed to parse the bounding box", e);
        }
    }

    private LiteralDataType parseLiteral(InputType it, Wps10Factory factory, IOParam param) {
        LiteralDataType literal = factory.createLiteralDataType();
        literal.setValue(param.value);
        literal.setDataType(param.attributes.get("datatype"));
        literal.setUom(param.attributes.get("uom"));

        return literal;
    }

    ResponseFormType parseResponseDocument(Map<String, Parameter<?>> outputs, String responseDefinition) {
        Wps10Factory factory = Wps10Factory.eINSTANCE;
        List<IOParam> ioParams = parseIOParameters(responseDefinition);

        ResponseFormType response = factory.createResponseFormType();
        ResponseDocumentType doc = factory.createResponseDocumentType();
        response.setResponseDocument(doc);

        for (IOParam ioParam : ioParams) {
            doc.getOutput().add(parseOutputDefinitionType(outputs, factory, ioParam, true));
        }

        return response;
    }

    OutputDefinitionType parseOutputDefinitionType(Map<String, Parameter<?>> outputs, Wps10Factory factory,
            IOParam ioParam, boolean inDocument) {
        if (!outputs.containsKey(ioParam.id)) {
            throw new WPSException("Unknown output " + ioParam.id);
        }

        OutputDefinitionType odt;
        if (inDocument) {
            DocumentOutputDefinitionType dout = factory.createDocumentOutputDefinitionType();
            dout.setAsReference(Boolean.parseBoolean(ioParam.attributes.get("asReference")));
            odt = dout;
        } else {
            odt = factory.createOutputDefinitionType();
        }
        odt.setIdentifier(Ows11Util.code(ioParam.id));
        odt.setEncoding(ioParam.attributes.get("encoding"));
        odt.setMimeType(ioParam.attributes.get("mimetype"));
        odt.setSchema(ioParam.attributes.get("schema"));
        odt.setUom(ioParam.attributes.get("uom"));

        return odt;
    }

    ResponseFormType parseRawDataOutput(Map<String, Parameter<?>> resultInfo, String rawOutputs) {
        Wps10Factory factory = Wps10Factory.eINSTANCE;
        ResponseFormType response = factory.createResponseFormType();

        List<IOParam> ioParams = parseIOParameters(rawOutputs);

        if (ioParams.size() == 0) {
            return response;
        }
        if (ioParams.size() > 1) {
            throw new WPSException("There can be only one RawDataOutput");
        }

        response.setRawDataOutput(parseOutputDefinitionType(resultInfo, factory, ioParams.get(0), false));

        return response;
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    class IOParam {
        String id;
        String value;
        Map<String, String> attributes;

        public IOParam(String id, String value, Map<String, String> attributes) {
            this.id = id;
            this.value = value;
            this.attributes = attributes;
        }

        public boolean isReference() {
            return attributes.keySet().contains("href") || attributes.keySet().contains("xlink:href");
        }
    }
}