Package org.geoserver.mbtiles.gs.wps

Source Code of org.geoserver.mbtiles.gs.wps.MBTilesProcess

/* (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.mbtiles.gs.wps;

import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.mbtiles.MBTilesGetMapOutputFormat;
import org.geoserver.platform.ServiceException;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wps.WPSStorageCleaner;
import org.geotools.data.DataUtilities;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.mbtiles.MBTilesFile;
import org.geotools.process.ProcessException;
import org.geotools.process.factory.DescribeParameter;
import org.geotools.process.factory.DescribeProcess;
import org.geotools.process.factory.DescribeResult;
import org.geotools.process.gs.GSProcess;
import org.geotools.referencing.CRS;
import org.geotools.styling.Style;
import org.geotools.util.logging.Logging;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

@DescribeProcess(title = "MBTiles", description = "MBTiles Process")
public class MBTilesProcess implements GSProcess {

    public static final String GRIDSET_NAME = "gridset";

    public static final String EPSG_900913 = "EPSG:900913";

    private static final int TEMP_DIR_ATTEMPTS = 10000;

    private static final Logger LOGGER = Logging.getLogger(MBTilesProcess.class);

    /**
     * GeoServer catalog
     */
    private Catalog catalog;

    /**
     * {@link WPSStorageCleaner} used for cleaning temporary files
     */
    private WPSStorageCleaner storage;

    /**
     * {@link MBTilesGetMapOutputFormat} instance used for creating the MBTiles file
     */
    private MBTilesGetMapOutputFormat mapOutput;

    public MBTilesProcess(Catalog catalog, MBTilesGetMapOutputFormat mapOutput,
            WPSStorageCleaner storage) {
        this.storage = storage;
        this.mapOutput = mapOutput;
        this.catalog = catalog;
    }

    public static File createTempDir(File baseDir) {
        String baseName = System.currentTimeMillis() + "-";

        for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
            File tempDir = new File(baseDir, baseName + counter);
            if (tempDir.mkdir()) {
                return tempDir;
            }
        }
        throw new IllegalStateException("Failed to create directory within " + TEMP_DIR_ATTEMPTS
                + " attempts (tried " + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1)
                + ')');
    }

    @DescribeResult(name = "mbtile", description = "Link to Compiled MBTiles File")
    public URL execute(
            @DescribeParameter(name = "layers", description = "Name of the input layer", collectionType = String.class) Collection<String> layerz,
            @DescribeParameter(name = "format", description = "Tiles format") String format,
            @DescribeParameter(name = "boundingbox", description = "Bounding Box of the final MBTile", min = 0) ReferencedEnvelope boundingbox,
            @DescribeParameter(name = "filename", description = "Name of the .mbtile file", min = 0) String filename,
            @DescribeParameter(name = "path", description = "Path to the directory where the .mbtile file can be stored ", min = 0) URL path,
            @DescribeParameter(name = "minZoom", description = "Minimum Zoom level to generate", min = 0) Integer minZoom,
            @DescribeParameter(name = "maxZoom", description = "Maximum Zoom level to generate", min = 0) Integer maxZoom,
            @DescribeParameter(name = "minRow", description = "Minimum Row to generate", min = 0) Integer minRow,
            @DescribeParameter(name = "maxRow", description = "Maximum Row to generate", min = 0) Integer maxRow,
            @DescribeParameter(name = "minColumn", description = "Minimum Column to generate", min = 0) Integer minColumn,
            @DescribeParameter(name = "maxColumn", description = "Maximum Column to generate", min = 0) Integer maxColumn,
            @DescribeParameter(name = "bgColor", description = "Background color", min = 0) String bgColor,
            @DescribeParameter(name = "transparency", description = "Transparency enabled or not", min = 0, defaultValue = "false") Boolean transparency,
            @DescribeParameter(name = "styleNames", description = "Name of the styles to use", min = 0, collectionType = String.class) Collection<String> styleNames,
            @DescribeParameter(name = "stylePath", description = "Path of the style to use", min = 0) URL stylePath,
            @DescribeParameter(name = "styleBody", description = "Body of the style to use", min = 0) String styleBody)
            throws IOException {
       
        // Extract the filename if present
        String name;

        if (filename != null && !filename.isEmpty()) {
            name = filename;
        } else if (!layerz.isEmpty()) {
            String firstLayer = layerz.iterator().next();
            name = firstLayer.substring(firstLayer.lastIndexOf(":") + 1);
        } else {
            throw new ProcessException("Layers parameter is empty");
        }
       
        // Initial check on the layers and styleNames size
        if(styleNames != null && styleNames.size() != layerz.size()){
            throw new ProcessException("Layers and styleNames must have the same size");
        }

        // Extract the file path if present
        final File file;

        if (path != null) {
            File urlToFile = DataUtilities.urlToFile(path);
            urlToFile.mkdirs();
            file = new File(urlToFile, name + ".mbtiles");
        } else {
            file = new File(createTempDir(storage.getStorage()), name + ".mbtiles");
        }

        // Create the MBTile file
        MBTilesFile mbtile = new MBTilesFile(file, true);
        try {
            // Initialize the MBTile file in order to avoid exceptions when accessing the geoPackage file
            mbtile.init();

            // Create the GetMap request to use
            GetMapRequest request = new GetMapRequest();

            // Create the layers map for the request
            ArrayList<MapLayerInfo> layers = new ArrayList<MapLayerInfo>();

            // Get the layers from the catalog
            for (String layername : layerz) {
                LayerInfo layerInfo = catalog.getLayerByName(layername);
                // Ensure the Layer is present
                if (layerInfo == null) {
                    throw new ServiceException("Layer not found: " + layername);
                }

                layers.add(new MapLayerInfo(layerInfo));
            }

            request.setLayers(layers);

            // Generate the bounding box if not present
            if (boundingbox == null) {
                try {

                    // generate one from requests layers

                    ReferencedEnvelope bbox = null;
                    for (MapLayerInfo l : request.getLayers()) {
                        ResourceInfo r = l.getResource();
                        // use native bbox
                        ReferencedEnvelope b = r.getNativeBoundingBox();
                        if (bbox != null) {
                            // transform
                            b = b.transform(bbox.getCoordinateReferenceSystem(), true);
                        }

                        if (bbox != null) {
                            bbox.include(b);
                        } else {
                            bbox = b;
                        }
                    }

                    request.setBbox(bbox);
                } catch (Exception e) {
                    String msg = "Must specify bbox, unable to derive from requested layers";
                    throw new RuntimeException(msg, e);
                }
            } else {
                request.setBbox(boundingbox);
            }

            // Extract CRS
            CoordinateReferenceSystem crs = boundingbox.getCoordinateReferenceSystem();

            // Set the request CRS
            if (crs == null) {
                // use crs of the layer
                ResourceInfo r = request.getLayers().iterator().next().getResource();
                crs = r.getCRS();
                request.setCrs(crs);
            } else {
                request.setCrs(crs);
            }

            // Set the request SRS
            request.setSRS(CRS.toSRS(crs));

            // Set Background color and Transparency
            if (bgColor != null && !bgColor.isEmpty()) {
                request.setBgColor(Color.decode(bgColor));
            }
            request.setTransparent(transparency == null ? false : transparency);

            // Add a style
            if (stylePath != null) {
                request.setStyleUrl(stylePath);
            } else if (styleBody != null && !styleBody.isEmpty()) {
                request.setStyleBody(styleBody);
            } else {
                request.setStyles(new ArrayList<Style>());
                if (styleNames != null && !styleNames.isEmpty()) {
                    for (String styleName : styleNames) {
                        StyleInfo info = catalog.getStyleByName(styleName);
                        if (info != null) {
                            request.getStyles().add(info.getStyle());
                        } else {
                            request.getStyles().add(null);
                        }
                    }
                }
                if (request.getStyles().isEmpty()) {
                    for (MapLayerInfo info : request.getLayers()) {
                        request.getStyles().add(info.getDefaultStyle());
                    }
                }
            }
            // Set the format of the mbtiles images
            request.setFormat("none");
            Map formatOptions = new HashMap();
            formatOptions.put("format", format);
            // Configure zoom levels if present
            if (minZoom != null) {
                formatOptions.put("min_zoom", minZoom);
            }
            if (maxZoom != null) {
                formatOptions.put("max_zoom", maxZoom);
            }
            if (minColumn != null) {
                formatOptions.put("min_column", minColumn);
            }
            if (maxColumn != null) {
                formatOptions.put("max_column", maxColumn);
            }
            if (minRow != null) {
                formatOptions.put("min_row", minRow);
            }
            if (maxRow != null) {
                formatOptions.put("max_row", maxRow);
            }
            // Set the gridSet name
            formatOptions.put(GRIDSET_NAME, EPSG_900913);
            // Add the format options to the request
            request.setFormatOptions(formatOptions);

            // Execute the requests
            mapOutput.addTiles(mbtile, request, name);
        } catch (Exception e) {
            if (LOGGER.isLoggable(Level.SEVERE)) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
            throw new ProcessException(e);
        } finally {
            // Close the connection
            if (mbtile != null) {
                try {
                    mbtile.close();
                } catch (Exception e) {
                    if (LOGGER.isLoggable(Level.SEVERE)) {
                        LOGGER.log(Level.SEVERE, e.getMessage(), e);
                    }
                }
            }
        }

        // Add to storage only if it is a temporary file
        if (path != null) {
            return DataUtilities.fileToURL(file);
        } else {
            return storage.getURL(file);
        }
    }
}
TOP

Related Classes of org.geoserver.mbtiles.gs.wps.MBTilesProcess

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.