/* (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;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.gwc.GWC;
import org.geoserver.platform.ServiceException;
import org.geoserver.tiles.AbstractTilesGetMapOutputFormat;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.WMS;
import org.geoserver.wms.WebMapService;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.mbtiles.MBTilesFile;
import org.geotools.mbtiles.MBTilesMetadata;
import org.geotools.mbtiles.MBTilesTile;
import org.geotools.referencing.CRS;
import org.geowebcache.grid.GridSubset;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.collect.Sets;
/**
*
* WMS GetMap Output Format for mbtiles
*
* @author Justin Deoliveira, Boundless
* @author Niels Charlier
*
*/
public class MBTilesGetMapOutputFormat extends AbstractTilesGetMapOutputFormat {
private final static CoordinateReferenceSystem SPHERICAL_MERCATOR;
private final static CoordinateReferenceSystem WGS_84;
static {
try {
SPHERICAL_MERCATOR = CRS.decode("EPSG:3857", true);
WGS_84 = CRS.decode("EPSG:4326", true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static class MbTilesFileWrapper implements TilesFile {
MBTilesFile mbTiles;
public MbTilesFileWrapper() throws IOException {
mbTiles = new MBTilesFile();
mbTiles.init();
}
public MbTilesFileWrapper(MBTilesFile file) throws IOException {
mbTiles = file;
}
@Override
public void setMetadata(String name, ReferencedEnvelope box, String imageFormat, int srid,
List<MapLayerInfo> mapLayers, int[] minmax, GridSubset gridSubset)
throws IOException, ServiceException {
MBTilesMetadata metadata = new MBTilesMetadata();
metadata.setName(name);
metadata.setVersion("0");
if (mapLayers.size() == 1) {
ResourceInfo r = mapLayers.get(0).getResource();
metadata.setDescription(r.getDescription());
metadata.setType(MBTilesMetadata.t_type.BASE_LAYER);
} else {
String descr = "";
for (MapLayerInfo l : mapLayers) {
descr += l.getResource().getDescription() + ", ";
}
descr = descr.substring(0, descr.length()-2);
metadata.setDescription(descr);
metadata.setType(MBTilesMetadata.t_type.OVERLAY);
}
try {
metadata.setBounds(box.transform(WGS_84, true));
} catch (Exception e) {
LOGGER.log(Level.WARNING, "Failed to transform bounding box", e);
}
// save metadata
metadata.setFormat(JPEG_MIME_TYPE.equals(imageFormat) ? MBTilesMetadata.t_format.JPEG
: MBTilesMetadata.t_format.PNG);
LOGGER.fine("Creating tile entry" + metadata.getName());
mbTiles.saveMetaData(metadata);
}
@Override
public void addTile(int zoom, int x, int y, byte[] data) throws IOException {
MBTilesTile tile = new MBTilesTile(zoom, x, y);
tile.setData(data);
mbTiles.saveTile(tile);
}
@Override
public File getFile() {
return mbTiles.getFile();
}
@Override
public void close() {
mbTiles.close();
}
}
static final String MIME_TYPE = "application/x-sqlite3";
static final String EXTENSION = ".mbtiles";
static final Set<String> NAMES = Sets.newHashSet("mbtiles");
//lazy loading converted bounds
protected ReferencedEnvelope convertedBounds = null;
public MBTilesGetMapOutputFormat(WebMapService webMapService, WMS wms, GWC gwc) {
super(MIME_TYPE, EXTENSION, NAMES, webMapService, wms, gwc);
}
@Override
protected TilesFile createTilesFile() throws IOException {
return new MbTilesFileWrapper();
}
@Override
protected ReferencedEnvelope bounds(GetMapRequest req) {
ReferencedEnvelope convertedBounds = null;
try {
convertedBounds = new ReferencedEnvelope(req.getBbox(), req.getCrs()).transform(SPHERICAL_MERCATOR, true);
} catch (Exception e) {
throw new ServiceException(e);
}
return convertedBounds;
}
@Override
protected CoordinateReferenceSystem getCoordinateReferenceSystem(GetMapRequest req) {
return SPHERICAL_MERCATOR;
}
@Override
protected String getSRS(GetMapRequest req) {
return "EPSG:900913";
}
/**
* Add tiles to an existing MBtile file
*
* @param mbtiles
* @param map
* @throws IOException
*/
public void addTiles(MBTilesFile mbtiles, GetMapRequest req, String name) throws IOException{
addTiles(new MbTilesFileWrapper(mbtiles), req, name);
}
}