nl.opengeogroep.safetymaps.server.admin.stripes.LayerActionBean.java Source code

Java tutorial

Introduction

Here is the source code for nl.opengeogroep.safetymaps.server.admin.stripes.LayerActionBean.java

Source

/*
 * Copyright (C) 2016 B3Partners B.V.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package nl.opengeogroep.safetymaps.server.admin.stripes;

import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import javax.naming.NamingException;
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.*;
import nl.opengeogroep.safetymaps.server.config.ConfiguredLayer;
import nl.opengeogroep.safetymaps.server.db.Cfg;
import static nl.opengeogroep.safetymaps.server.db.DB.qr;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

/**
 *
 * @author Matthijs Laan
 */
@StrictBinding
@UrlBinding("/admin/action/layers/{layer}")
public class LayerActionBean implements ActionBean, ValidationErrorHandler {

    private static final Log log = LogFactory.getLog("admin.layers");

    private static final String JSP = "/WEB-INF/jsp/admin/layers.jsp";

    private static final String TABLE = "organisation.wms ";

    private ActionBeanContext context;

    private List<ConfiguredLayer> layers = new ArrayList();

    @ValidateNestedProperties({ @Validate(field = "url", required = true, trim = true, maxlength = 255),
            @Validate(field = "getcapabilities"), @Validate(field = "enabled"),
            //        @Validate(field = "baselayer"),
            @Validate(field = "index"),
            @Validate(field = "legend", trim = true, maxlength = 255)/*,
                                                                     @Validate(field = "notes")*/
    })
    private ConfiguredLayer layer = new ConfiguredLayer();

    @Validate
    private String tab;

    @Validate
    private String name;

    @Validate
    private boolean visible = true;

    @Validate
    private boolean hidefeatureinfo = true;

    @Validate
    private Integer featureInfoRadius = null;

    @Validate
    private String params;

    @Validate
    private String layersParam;

    @Validate
    private boolean dpiConversionEnabled = true;

    @Validate
    private boolean singleTile = true;

    @Validate
    private boolean hiDPI = true;

    @Validate
    private Double maxResolution;

    @Validate
    private String layerToggleKey;

    private String mapFilesJson = "{}";

    private boolean vrhObjectsEnabled = false;

    // <editor-fold defaultstate="collapsed" desc="getters and setters">
    @Override
    public ActionBeanContext getContext() {
        return context;
    }

    @Override
    public void setContext(ActionBeanContext context) {
        this.context = context;
    }

    public List<ConfiguredLayer> getLayers() {
        return layers;
    }

    public void setLayers(List<ConfiguredLayer> layers) {
        this.layers = layers;
    }

    public ConfiguredLayer getLayer() {
        return layer;
    }

    public void setLayer(ConfiguredLayer layer) {
        this.layer = layer;
    }

    public String getTab() {
        return tab;
    }

    public void setTab(String tab) {
        this.tab = tab;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public boolean isHidefeatureinfo() {
        return hidefeatureinfo;
    }

    public void setHidefeatureinfo(boolean hidefeatureinfo) {
        this.hidefeatureinfo = hidefeatureinfo;
    }

    public Integer getFeatureInfoRadius() {
        return featureInfoRadius;
    }

    public void setFeatureInfoRadius(Integer featureInfoRadius) {
        this.featureInfoRadius = featureInfoRadius;
    }

    public boolean isSingleTile() {
        return singleTile;
    }

    public void setSingleTile(boolean singleTile) {
        this.singleTile = singleTile;
    }

    public boolean isHiDPI() {
        return hiDPI;
    }

    public void setHiDPI(boolean hiDPI) {
        this.hiDPI = hiDPI;
    }

    public Double getMaxResolution() {
        return maxResolution;
    }

    public void setMaxResolution(Double maxResolution) {
        this.maxResolution = maxResolution;
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public String getMapFilesJson() {
        return mapFilesJson;
    }

    public void setMapFilesJson(String mapFilesJson) {
        this.mapFilesJson = mapFilesJson;
    }

    public String getLayersParam() {
        return layersParam;
    }

    public void setLayersParam(String layersParam) {
        this.layersParam = layersParam;
    }

    public boolean isDpiConversionEnabled() {
        return dpiConversionEnabled;
    }

    public void setDpiConversionEnabled(boolean dpiConversionEnabled) {
        this.dpiConversionEnabled = dpiConversionEnabled;
    }

    public String getLayerToggleKey() {
        return layerToggleKey;
    }

    public void setLayerToggleKey(String layerToggleKey) {
        this.layerToggleKey = layerToggleKey;
    }

    public boolean isVrhObjectsEnabled() {
        return vrhObjectsEnabled;
    }

    public void setVrhObjectsEnabled(boolean vrhObjectsEnabled) {
        this.vrhObjectsEnabled = vrhObjectsEnabled;
    }
    // </editor-fold>

    @Before
    private void loadInfo() throws NamingException, SQLException {
        layers = qr().query("select * from " + TABLE + " where layertype = 'WMS' order by gid",
                new BeanListHandler<>(ConfiguredLayer.class));

        vrhObjectsEnabled = qr().query("select 1 from organisation.modules where name='vrh_objects' and enabled",
                new ScalarHandler<>()) != null;
    }

    @Override
    public Resolution handleValidationErrors(ValidationErrors errors) throws Exception {
        loadInfo();
        return list();
    }

    @DefaultHandler
    @DontValidate
    public Resolution list() throws Exception {
        return new ForwardResolution(JSP);
    }

    @Before(stages = LifecycleStage.BindingAndValidation)
    private void findMapfiles() {
        try {
            JSONArray a = new JSONArray();
            File search = Cfg.getPath("static_mapserver_searchdirs");

            if (search != null) {
                for (File f : FileUtils.listFiles(search, new String[] { "map" }, true)) {
                    JSONObject m = new JSONObject();
                    m.put("path", f.getPath().substring(search.getPath().length() + 1));
                    a.put(m);

                    // Naive mapfile parser. Perhaps replace by JavaScript client-side
                    // GetCap parsing
                    JSONArray l = new JSONArray();
                    m.put("layers", l);
                    LineIterator it = FileUtils.lineIterator(f, "US-ASCII");
                    try {
                        while (it.hasNext()) {
                            String line = it.nextLine().trim();
                            if (line.equals("LAYER")) {
                                String n = it.nextLine().trim();
                                n = n.substring(6, n.length() - 1);
                                l.put(n);
                            }
                        }
                    } finally {
                        it.close();
                    }
                }
            }
            mapFilesJson = a.toString(4);
        } catch (Exception e) {
        }
    }

    @Before(stages = LifecycleStage.BindingAndValidation, on = { "edit", "save" })
    public void loadLayer() throws NamingException, SQLException {

        String s = context.getRequest().getParameter("id");
        if (StringUtils.isNotBlank(s)) {
            Integer id = Integer.parseInt(s);

            layer = qr().query("select * from " + TABLE + " where gid = ?",
                    new BeanHandler<>(ConfiguredLayer.class), id);

            String n = layer.getName();
            int i;
            if (n != null && (i = n.indexOf("\\")) != -1) {
                tab = n.substring(0, i);
                name = n.substring(i + 1);
            } else {
                if (Boolean.TRUE.equals(layer.isGetcapabilities())) {
                    tab = n;
                } else {
                    name = n;
                }
            }

            JSONObject options = null;
            if (layer.getOptions() != null) {
                try {
                    options = new JSONObject(layer.getOptions());
                } catch (JSONException e) {
                }
            }
            if (options != null) {
                visible = options.optBoolean("visibility", visible);
                hidefeatureinfo = options.optBoolean("hidefeatureinfo", false);
                featureInfoRadius = options.has("featureInfoRadius") ? options.getInt("featureInfoRadius") : null;
                maxResolution = options.has("maxResolution") ? options.getDouble("maxResolution") : null;
                singleTile = options.optBoolean("singleTile", true);
                hiDPI = options.optBoolean("hiDPI", false);
            }

            layerToggleKey = layer.getNotes();

            try {
                params = "";
                dpiConversionEnabled = false;
                JSONObject p = new JSONObject(layer.getParams());
                for (String key : (Set<String>) p.keySet()) {
                    if ("layers".equalsIgnoreCase(key)) {
                        layersParam = p.getString(key);
                    } else if ("map_resolution".equalsIgnoreCase(key)) {
                        dpiConversionEnabled = true;
                    } else {
                        if (params.length() > 0) {
                            params += ",";
                        }
                        params += key + "=" + p.getString(key);
                    }
                }
            } catch (Exception e) {
            }
        }
    }

    @DontValidate
    public Resolution edit() throws Exception {
        return new ForwardResolution(JSP);
    }

    public Resolution save() throws Exception {
        if (tab != null) {
            name = tab + (name == null ? "" : '\\' + name);
            layer.setParent(null);
        } else {
            layer.setParent("#overlaypanel_b2");
        }
        JSONObject p = new JSONObject();
        if (params != null) {
            for (String s : params.split(",")) {
                String[] parts = s.split("=", 2);
                if (parts.length == 2) {
                    p.put(parts[0], parts[1]);
                }
            }
        }

        if (dpiConversionEnabled) {
            p.put("map_resolution", 58); // Convert ArcGIS 90 dpi to 72 dpi MapServer resolution: 72 / (90 / 72) = 57.6 = 58
        }
        p.put("layers", layersParam);

        // XXX
        layer.setNotes(layerToggleKey);

        JSONObject options = new JSONObject();
        try {
            options = new JSONObject(layer.getOptions());
        } catch (Exception e) {
        }
        options.put("visibility", visible);
        options.put("hidefeatureinfo", hidefeatureinfo);
        options.put("singleTile", singleTile);
        options.put("hiDPI", hiDPI);
        if (featureInfoRadius != null) {
            options.put("featureInfoRadius", featureInfoRadius);
        } else {
            options.remove("featureInfoRadius");
        }
        if (maxResolution != null) {
            options.put("maxResolution", maxResolution);
        } else {
            options.remove("maxResolution");
        }

        Object[] qparams = new Object[] { name, layer.getUrl(), layer.isProxy(), layer.isEnabled(),
                layer.isBaselayer(), p.toString(), options.toString(), layer.isGetcapabilities(), layer.getParent(),
                layer.getPl(), layer.getLayertype(), layer.getIndex(), layer.getNotes(), layer.getLegend() };
        if (layer.getGid() == null) {
            log.debug("inserting new layer: " + Arrays.toString(qparams));
            Integer newId = qr().insert("insert into " + TABLE
                    + "(name,url,proxy,enabled,baselayer,params,options,getcapabilities,parent,pl,layertype,index,abstract,legend) "
                    + "values(?,?,?,?,?,?::json,?::json,?,?,?,?,?,?,?)", new ScalarHandler<Integer>(), qparams);
            layer.setGid(newId);
            log.debug("new layer id: " + newId);
        } else {
            log.debug("updating layer id " + layer.getGid() + ": " + Arrays.toString(qparams));
            qr().update("update " + TABLE
                    + "set name=?,url=?,proxy=?,enabled=?,baselayer=?,params=?::json,options=?::json,getcapabilities=?,parent=?,pl=?,layertype=?,index=?,abstract=?,legend=? "
                    + "where gid=" + layer.getGid(), qparams);
        }
        Cfg.settingsUpdated();

        getContext().getMessages().add(new SimpleMessage("Laag opgeslagen."));
        return new RedirectResolution(this.getClass()).flash(this);
    }

    @DontValidate
    public Resolution delete() throws Exception {
        String id = context.getRequest().getParameter("id");
        if (id != null) {
            qr().update("delete from " + TABLE + " where gid=?::integer", id);
            getContext().getMessages().add(new SimpleMessage("Laag verwijderd."));
        } else {
            getContext().getMessages().add(new SimpleMessage("Geen laag id om te verwijderen!"));
        }
        return new RedirectResolution(this.getClass()).flash(this);
    }

    @DontValidate
    public Resolution cancel() {
        return new RedirectResolution(this.getClass()).flash(this);
    }

}