com.boundlessgeo.geoserver.api.controllers.MapController.java Source code

Java tutorial

Introduction

Here is the source code for com.boundlessgeo.geoserver.api.controllers.MapController.java

Source

/* (c) 2014 Boundless, http://boundlessgeo.com
 * This code is licensed under the GPL 2.0 license.
 */
package com.boundlessgeo.geoserver.api.controllers;

import static org.geoserver.catalog.Predicates.equal;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nullable;

import com.boundlessgeo.geoserver.json.JSONArr;
import com.boundlessgeo.geoserver.json.JSONObj;
import org.apache.commons.httpclient.util.DateUtil;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerGroupInfo.Mode;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.PublishedInfo;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.catalog.util.CloseableIterator;
import org.geoserver.config.GeoServer;
import org.geoserver.platform.resource.Paths;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resource.Type;
import org.geotools.feature.NameImpl;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.util.logging.Logging;
import com.boundlessgeo.geoserver.api.exceptions.NotFoundException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.vividsolutions.jts.geom.Envelope;

@Controller
@RequestMapping("/api/maps")
public class MapController extends ApiController {

    static Logger LOG = Logging.getLogger(LayerController.class);

    @Autowired
    public MapController(GeoServer geoServer) {
        super(geoServer);
    }

    @RequestMapping(value = "/{wsName}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    @ResponseStatus(HttpStatus.CREATED)
    public @ResponseBody JSONObj create(@PathVariable String wsName, @RequestBody JSONObj obj) {
        String name = obj.str("name");
        String title = obj.str("title");
        String description = obj.str("abstract");

        String user = SecurityContextHolder.getContext().getAuthentication().getName();
        Date created = new Date();

        CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;
        if (obj.has("proj")) {
            String srs = obj.str("proj");
            try {
                crs = CRS.decode(srs);
            } catch (FactoryException e) {
                LOG.log(Level.FINE, wsName + "." + name + " unrecorgnized proj:" + srs, e);
            }
        }
        Envelope envelope = IO.bounds(obj.object("bbox"));
        ReferencedEnvelope bounds = new ReferencedEnvelope(envelope, crs);

        Catalog cat = geoServer.getCatalog();
        LayerGroupInfo map = cat.getFactory().createLayerGroup();
        map.setName(name);
        map.setAbstract(description);
        map.setTitle(title);
        map.setMode(Mode.SINGLE);
        map.setWorkspace(findWorkspace(wsName));
        map.setBounds(bounds);

        Metadata.created(map, created);
        Metadata.modified(map, created);

        cat.add(map);
        return mapDetails(new JSONObj(), map, wsName);
    }

    @RequestMapping(value = "/{wsName}/{name}", method = RequestMethod.DELETE)
    public @ResponseBody JSONArr delete(@PathVariable String wsName, @PathVariable String name) {
        LayerGroupInfo map = findMap(wsName, name);
        geoServer.getCatalog().remove(map);

        return list(wsName);
    }

    @RequestMapping(value = "/{wsName}/{name}", method = RequestMethod.GET)
    public @ResponseBody JSONObj get(@PathVariable String wsName, @PathVariable String name) {
        LayerGroupInfo map = findMap(wsName, name);
        return mapDetails(new JSONObj(), map, wsName);
    }

    @RequestMapping(value = "/{wsName}/{name}", method = RequestMethod.PATCH)
    public @ResponseBody JSONObj patch(@PathVariable String wsName, @PathVariable String name,
            @RequestBody JSONObj obj) {
        return put(wsName, name, obj);
    }

    @RequestMapping(value = "/{wsName}/{name}", method = RequestMethod.PUT)
    public @ResponseBody JSONObj put(@PathVariable String wsName, @PathVariable String name,
            @RequestBody JSONObj obj) {
        LayerGroupInfo map = findMap(wsName, name);

        if (obj.has("name")) {
            map.setName(obj.str("name"));
        }
        if (obj.has("title")) {
            map.setTitle(obj.str("title"));
        }
        if (obj.has("abstract")) {
            map.setAbstract(obj.str("abstract"));
        }
        if (obj.has("proj") && obj.has("bbox")) {
            CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;
            if (obj.has("proj")) {
                String srs = obj.str("proj");
                try {
                    crs = CRS.decode(srs);
                } catch (FactoryException e) {
                    LOG.log(Level.FINE, wsName + "." + name + " unrecorgnized proj:" + srs, e);
                }
            }
            Envelope envelope = IO.bounds(obj.object("bbox"));
            ReferencedEnvelope bounds = new ReferencedEnvelope(envelope, crs);
            map.setBounds(bounds);
        }
        String user = SecurityContextHolder.getContext().getAuthentication().getName();
        map.getMetadata().put("user", user);

        map.getMetadata().put("modified", new Date());

        if (obj.has("change")) {
            map.getMetadata().put("change", obj.str("change"));
        } else {
            map.getMetadata().put("change", "modified " + obj.keys());
        }
        return mapDetails(new JSONObj(), map, wsName);
    }

    @RequestMapping(value = "/{wsName}", method = RequestMethod.GET)
    public @ResponseBody JSONArr list(@PathVariable String wsName) {
        JSONArr arr = new JSONArr();

        Catalog cat = geoServer.getCatalog();

        if ("default".equals(wsName)) {
            WorkspaceInfo def = cat.getDefaultWorkspace();
            if (def != null) {
                wsName = def.getName();
            }
        }

        CloseableIterator<LayerGroupInfo> it = cat.list(LayerGroupInfo.class, equal("workspace.name", wsName));
        try {
            while (it.hasNext()) {
                LayerGroupInfo map = it.next();
                if (checkMap(map)) {
                    JSONObj obj = arr.addObject();
                    map(obj, map, wsName);
                }
            }
        } finally {
            it.close();
        }

        return arr;
    }

    @RequestMapping(value = "/{wsName}/{name}/layers", method = RequestMethod.GET)
    public @ResponseBody JSONArr layers(@PathVariable String wsName, @PathVariable String name) {
        LayerGroupInfo m = findMap(wsName, name);

        JSONArr arr = new JSONArr();
        for (LayerInfo l : m.layers()) {
            IO.layer(arr.addObject(), l);
        }
        return arr;
    }

    @RequestMapping(value = "/{wsName}/{name}/layers", method = RequestMethod.PUT)
    public @ResponseBody void layers(@RequestBody JSONArr layers, @PathVariable String wsName,
            @PathVariable String name) {
        LayerGroupInfo m = findMap(wsName, name);

        List<MapLayer> mapLayers = new ArrayList();
        for (int i = 0; i < m.getLayers().size(); i++) {
            mapLayers.add(new MapLayer(m.getLayers().get(i), m.getStyles().get(i)));
        }

        Map<String, MapLayer> map = Maps.uniqueIndex(mapLayers, new Function<MapLayer, String>() {
            @Nullable
            @Override
            public String apply(@Nullable MapLayer input) {
                return input.layer.getName();
            }
        });

        Catalog cat = geoServer.getCatalog();
        List<PublishedInfo> reLayers = new ArrayList<PublishedInfo>();
        List<StyleInfo> reStyles = new ArrayList<StyleInfo>();

        for (JSONObj l : Lists.reverse(Lists.newArrayList(layers.objects()))) {
            String layerName = l.str("name");
            String layerWorkspace = l.str("worskpace");

            MapLayer mapLayer = map.get(layerName);
            if (mapLayer == null) {
                LayerInfo layer = layerWorkspace != null
                        ? cat.getLayerByName(new NameImpl(layerWorkspace, layerName))
                        : cat.getLayerByName(layerName);
                if (layer != null) {
                    mapLayer = new MapLayer(layer, layer.getDefaultStyle());
                }
            }

            if (mapLayer == null) {
                throw new NotFoundException("No such layer: " + l.toString());
            }

            reLayers.add(mapLayer.layer);
            reStyles.add(mapLayer.style);
        }

        m.getLayers().clear();
        m.getLayers().addAll(reLayers);

        m.getStyles().clear();
        m.getStyles().addAll(reStyles);

        cat.save(m);
    }

    private boolean checkMap(LayerGroupInfo map) {
        if (map.getMode() != Mode.SINGLE) {
            return false;
        }
        for (int i = 0; i < map.styles().size(); i++) {
            LayerInfo style = map.layers().get(i);
            List<PublishedInfo> layer = map.getLayers();
            if (layer instanceof LayerInfo && style != ((LayerInfo) layer).getDefaultStyle()) {
                return false;
            } else if (layer instanceof LayerGroupInfo && style != ((LayerGroupInfo) layer).getRootLayerStyle()) {
                return false;
            }
        }
        return true;
    }

    List<PublishedInfo> layers(LayerGroupInfo map) {
        List<PublishedInfo> layers = map.getLayers();
        return Lists.reverse(layers);
    }

    JSONObj map(JSONObj obj, LayerGroupInfo map, String wsName) {
        obj.put("name", map.getName()).put("workspace", wsName).put("title", map.getTitle()).put("abstract",
                map.getAbstract());

        ReferencedEnvelope bounds = map.getBounds();
        IO.proj(obj.putObject("proj"), bounds.getCoordinateReferenceSystem(), null);
        IO.bounds(obj.putObject("bbox"), bounds);

        if (!obj.has("modified")) {
            String path = Paths.path("workspaces", wsName, "layergroups", String.format("%s.xml", map.getName()));
            Resource r = geoServer.getCatalog().getResourceLoader().get(path);
            if (r.getType() == Type.RESOURCE) {
                long modified = r.lastmodified();
                String time = DateUtil.formatDate(new Date(modified));
                obj.put("modified", time);
            }
        }

        obj.put("layer_count", map.getLayers().size());

        return obj;
    }

    JSONObj mapDetails(JSONObj obj, LayerGroupInfo map, String wsName) {
        map(obj, map, wsName);

        List<PublishedInfo> published = layers(map);
        JSONArr layers = obj.putArray("layers");
        for (PublishedInfo l : published) {
            JSONObj item = layers.addObject();
            item.put("name", l.getName());
            if (l.getTitle() != null) {
                item.put("title", l.getTitle());
            }
            if (l.getAbstract() != null) {
                item.put("abstract", l.getAbstract());
            }
            if (l instanceof LayerInfo) {
                LayerInfo info = (LayerInfo) l;
                item.put("resource", info.getResource().getName());

                StoreInfo store = info.getResource().getStore();
                if (store != null) {
                    WorkspaceInfo workspace = store.getWorkspace();
                    String name = workspace.getName();
                    item.put("workspace", name);
                }
            } else if (l instanceof LayerGroupInfo) {
                LayerGroupInfo group = (LayerGroupInfo) l;
                item.put("group", group.getMode().name());
                item.put("workspace", group.getWorkspace().getName());
                item.put("layer_count", group.getLayers().size());
            }

        }

        return IO.metadata(obj, map);
    }

    WorkspaceInfo findWorkspace(String wsName) {
        Catalog cat = geoServer.getCatalog();
        WorkspaceInfo ws;
        if ("default".equals(wsName)) {
            ws = cat.getDefaultWorkspace();
        } else {
            ws = cat.getWorkspaceByName(wsName);
        }
        if (ws == null) {
            throw new RuntimeException("Unable to find workspace " + wsName);
        }
        return ws;
    }

    LayerGroupInfo findMap(String wsName, String name) {
        Catalog cat = geoServer.getCatalog();
        LayerGroupInfo m = cat.getLayerGroupByName(wsName, name);
        if (m == null) {
            throw new NotFoundException(String.format("No such map %s:%s", wsName, name));
        }
        return m;
    }

    static class MapLayer {
        PublishedInfo layer;
        StyleInfo style;

        public MapLayer(PublishedInfo layer, StyleInfo style) {
            this.layer = layer;
            this.style = style;
        }
    }
}