org.geoserver.wps.web.ComplexInputPanel.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.wps.web.ComplexInputPanel.java

Source

/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
 * (c) 2001 - 2013 OpenPlans
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.wps.web;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.transform.TransformerException;

import org.apache.wicket.Page;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.web.GeoServerApplication;
import org.geoserver.wps.web.InputParameterValues.ParameterType;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.util.logging.Logging;

/**
 * Allows the user to edit a complex input parameter providing a variety of different editors
 * depending on the parameter type
 * 
 * @author Andrea Aime - OpenGeo
 */
@SuppressWarnings("serial")
public class ComplexInputPanel extends Panel {
    static final Logger LOGGER = Logging.getLogger(WPSRequestBuilderPanel.class);

    private DropDownChoice typeChoice;

    PropertyModel valueModel;

    List<String> mimeTypes;

    ModalWindow subprocesswindow;

    public ComplexInputPanel(String id, InputParameterValues pv, int valueIndex) {
        super(id);
        setOutputMarkupId(true);
        setDefaultModel(new PropertyModel(pv, "values[" + valueIndex + "]"));
        valueModel = new PropertyModel(getDefaultModel(), "value");
        mimeTypes = pv.getSupportedMime();

        List<ParameterType> ptypes = pv.getSupportedTypes();
        ptypes.remove(ParameterType.LITERAL);
        typeChoice = new DropDownChoice("type", new PropertyModel(getDefaultModelObject(), "type"), ptypes);
        add(typeChoice);

        subprocesswindow = new ModalWindow("subprocessPopupWindow");
        subprocesswindow.setInitialWidth(700);
        subprocesswindow.setInitialHeight(500);
        add(subprocesswindow);
        subprocesswindow.setPageCreator(new ModalWindow.PageCreator() {

            public Page createPage() {
                return new SubProcessBuilder((ExecuteRequest) subprocesswindow.getDefaultModelObject(),
                        subprocesswindow);
            }
        });

        updateEditor();

        typeChoice.add(new AjaxFormComponentUpdatingBehavior("onchange") {

            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                updateEditor();
                target.addComponent(ComplexInputPanel.this);
            }

        });
    }

    void updateEditor() {
        // remove the old editor
        if (get("editor") != null) {
            remove("editor");
        }

        ParameterType pt = (ParameterType) typeChoice.getModelObject();
        if (pt == ParameterType.TEXT) {
            // an internal vector layer
            if (!(valueModel.getObject() instanceof String)) {
                valueModel.setObject("");
            }

            // data as plain text
            Fragment f = new Fragment("editor", "text", this);
            DropDownChoice mimeChoice = new DropDownChoice("mime", new PropertyModel(getDefaultModel(), "mime"),
                    mimeTypes);
            f.add(mimeChoice);

            f.add(new TextArea("textarea", valueModel));
            add(f);
        } else if (pt == ParameterType.VECTOR_LAYER) {
            // an internal vector layer
            if (!(valueModel.getObject() instanceof VectorLayerConfiguration)) {
                valueModel.setObject(new VectorLayerConfiguration());
            }

            new PropertyModel(getDefaultModel(), "mime").setObject("text/xml");
            Fragment f = new Fragment("editor", "vectorLayer", this);
            DropDownChoice layer = new DropDownChoice("layer", new PropertyModel(valueModel, "layerName"),
                    getVectorLayerNames());
            f.add(layer);
            add(f);
        } else if (pt == ParameterType.RASTER_LAYER) {
            // an internal raster layer
            if (!(valueModel.getObject() instanceof RasterLayerConfiguration)) {
                valueModel.setObject(new RasterLayerConfiguration());
            }

            Fragment f = new Fragment("editor", "rasterLayer", this);
            final DropDownChoice layer = new DropDownChoice("layer", new PropertyModel(valueModel, "layerName"),
                    getRasterLayerNames());
            f.add(layer);
            add(f);

            // we need to update the raster own bounding box as wcs requests
            // mandate a spatial extent (why oh why???)
            layer.add(new AjaxFormComponentUpdatingBehavior("onchange") {

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    String name = layer.getDefaultModelObjectAsString();
                    LayerInfo li = GeoServerApplication.get().getCatalog().getLayerByName(name);
                    ReferencedEnvelope spatialDomain = li.getResource().getNativeBoundingBox();
                    ((RasterLayerConfiguration) valueModel.getObject()).setSpatialDomain(spatialDomain);
                }
            });
        } else if (pt == ParameterType.REFERENCE) {
            // an external reference
            if (!(valueModel.getObject() instanceof ReferenceConfiguration)) {
                valueModel.setObject(new ReferenceConfiguration());
            }

            Fragment f = new Fragment("editor", "reference", this);
            final DropDownChoice method = new DropDownChoice("method", new PropertyModel(valueModel, "method"),
                    Arrays.asList(ReferenceConfiguration.Method.GET, ReferenceConfiguration.Method.POST));
            f.add(method);

            DropDownChoice mimeChoice = new DropDownChoice("mime", new PropertyModel(valueModel, "mime"),
                    mimeTypes);
            f.add(mimeChoice);

            f.add(new TextField("url", new PropertyModel(valueModel, "url")).setRequired(true));
            final TextArea body = new TextArea("body", new PropertyModel(valueModel, "body"));
            add(body);

            final WebMarkupContainer bodyContainer = new WebMarkupContainer("bodyContainer");
            f.add(bodyContainer);
            bodyContainer.setOutputMarkupId(true);
            bodyContainer.add(body);
            bodyContainer.setVisible(false);

            method.add(new AjaxFormComponentUpdatingBehavior("onchange") {

                @Override
                protected void onUpdate(AjaxRequestTarget target) {
                    boolean post = method.getModelObject() == ReferenceConfiguration.Method.POST;
                    bodyContainer.setVisible(post);
                    body.setRequired(post);
                    target.addComponent(ComplexInputPanel.this);
                }
            });

            add(f);
        } else if (pt == ParameterType.SUBPROCESS) {
            if (!(valueModel.getObject() instanceof ExecuteRequest)) {
                valueModel.setObject(new ExecuteRequest());
            }

            Fragment f = new Fragment("editor", "subprocess", this);
            f.add(new AjaxLink("edit") {

                @Override
                public void onClick(AjaxRequestTarget target) {
                    subprocesswindow.setDefaultModel(valueModel);
                    subprocesswindow.show(target);
                }
            });

            final TextArea xml = new TextArea("xml");
            if (((ExecuteRequest) valueModel.getObject()).processName != null) {
                try {
                    xml.setModelObject(getExecuteXML());
                } catch (Throwable t) {
                    xml.setModel(new Model(""));
                }
            } else {
                xml.setModel(new Model(""));
            }
            xml.setOutputMarkupId(true);
            f.add(xml);

            subprocesswindow.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {

                public void onClose(AjaxRequestTarget target) {
                    // turn the GUI request into an actual WPS request
                    xml.setModelObject(getExecuteXML());

                    target.addComponent(xml);
                }

            });

            add(f);
        } else {
            error("Unsupported parameter type");
        }
    }

    String getExecuteXML() {
        WPSExecuteTransformer tx = new WPSExecuteTransformer();
        tx.setIndentation(2);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try {
            tx.transform(valueModel.getObject(), out);
        } catch (TransformerException e) {
            LOGGER.log(Level.SEVERE, "Error generating xml request", e);
            error(e);
        }
        String executeXml = out.toString();
        return executeXml;
    }

    List<String> getVectorLayerNames() {
        Catalog catalog = GeoServerApplication.get().getCatalog();

        List<String> result = new ArrayList<String>();
        for (LayerInfo li : catalog.getLayers()) {
            if (li.getResource() instanceof FeatureTypeInfo) {
                result.add(li.getResource().getPrefixedName());
            }
        }
        return result;
    }

    List<String> getRasterLayerNames() {
        Catalog catalog = GeoServerApplication.get().getCatalog();

        List<String> result = new ArrayList<String>();
        for (LayerInfo li : catalog.getLayers()) {
            if (li.getResource() instanceof CoverageInfo) {
                result.add(li.getResource().getPrefixedName());
            }
        }
        return result;
    }
}