/**
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @author Arne Kepp, The Open Planning Project, Copyright 2008
*/
package org.geowebcache.service.gmaps;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.geowebcache.GeoWebCacheException;
import org.geowebcache.conveyor.ConveyorTile;
import org.geowebcache.grid.GridSetBroker;
import org.geowebcache.layer.TileLayer;
import org.geowebcache.layer.TileLayerDispatcher;
import org.geowebcache.mime.MimeException;
import org.geowebcache.mime.MimeType;
import org.geowebcache.service.Service;
import org.geowebcache.service.ServiceException;
import org.geowebcache.storage.StorageBroker;
import org.geowebcache.util.ServletUtils;
/**
* Class to convert from Google Maps coordinates into the internal representation of a tile.
*/
public class GMapsConverter extends Service {
public static final String SERVICE_GMAPS = "gmaps";
private StorageBroker sb;
private TileLayerDispatcher tld;
private GridSetBroker gsb;
/**
* Protected no-argument constructor to allow run-time instrumentation
*/
protected GMapsConverter() {
super(SERVICE_GMAPS);
}
public GMapsConverter(StorageBroker sb, TileLayerDispatcher tld, GridSetBroker gsb) {
super(SERVICE_GMAPS);
this.sb = sb;
this.tld = tld;
this.gsb = gsb;
}
public ConveyorTile getConveyor(HttpServletRequest request, HttpServletResponse response)
throws ServiceException, GeoWebCacheException {
String layerId = super.getLayersParameter(request);
String encoding = request.getCharacterEncoding();
Map<String, String[]> params = request.getParameterMap();
String strFormat = ServletUtils.stringFromMap(params, encoding, "format");
String strZoom = ServletUtils.stringFromMap(params, encoding, "zoom");
String strX = ServletUtils.stringFromMap(params, encoding, "x");
String strY = ServletUtils.stringFromMap(params, encoding, "y");
String strCached = ServletUtils.stringFromMap(params, encoding, "cached");
String strMetaTiled = ServletUtils.stringFromMap(params, encoding, "metatiled");
long[] gridLoc = GMapsConverter.convert(Integer.parseInt(strZoom), Integer.parseInt(strX),
Integer.parseInt(strY));
String layers = ServletUtils.stringFromMap(params, encoding, "layers");
if (layers == null || layers.length() == 0) {
layers = ServletUtils.stringFromMap(params, encoding, "layer");
}
TileLayer tileLayer = tld.getTileLayer(layers);
Map<String, String> filteringParameters = tileLayer.getModifiableParameters(params, encoding);
MimeType mimeType = null;
try {
if (strFormat == null) {
strFormat = "image/png";
}
mimeType = MimeType.createFromFormat(strFormat);
} catch (MimeException me) {
throw new ServiceException("Unable to determine requested format, " + strFormat);
}
ConveyorTile ret = new ConveyorTile(sb, layerId, gsb.WORLD_EPSG3857.getName(), gridLoc,
mimeType, filteringParameters, request, response);
if (strCached != null && !Boolean.parseBoolean(strCached)) {
ret.setRequestHandler(ConveyorTile.RequestHandler.SERVICE);
if (strMetaTiled != null && !Boolean.parseBoolean(strMetaTiled)) {
ret.setHint("not_cached,not_metatiled");
} else {
ret.setHint("not_cached");
}
}
return ret;
}
/**
* NB The following code is shared across Google Maps, Mobile Google Maps and Virtual Earth
*/
public void handleRequest(ConveyorTile tile) throws GeoWebCacheException {
if (tile.getHint() != null) {
// boolean requestTiled = true;
if (tile.getHint().equals("not_cached,not_metatiled")) {
// requestTiled = false;
} else if (!tile.getHint().equals("not_cached")) {
throw new GeoWebCacheException("Hint " + tile.getHint() + " is not known.");
}
TileLayer tl = tld.getTileLayer(tile.getLayerId());
if (tl == null) {
throw new GeoWebCacheException("Unknown layer " + tile.getLayerId());
}
if (!tl.isCacheBypassAllowed().booleanValue()) {
throw new GeoWebCacheException("Layer " + tile.getLayerId()
+ " is not configured to allow bypassing the cache.");
}
tile.setTileLayer(tl);
tl.getNoncachedTile(tile);
Service.writeTileResponse(tile, false);
}
}
/**
* Convert Google's tiling coordinates into an {x,y,x}
*
* see http://code.google.com/apis/maps/documentation/overlays.html#Custom_Map_Types
*
* @param quadKey
* @return
*/
public static long[] convert(long zoomLevel, long x, long y) throws ServiceException {
// Extent is the total number of tiles in y direction
long extent = (long) Math.pow(2, zoomLevel);
if (x < 0 || x > extent - 1) {
throw new ServiceException("The X coordinate is not sane: " + x);
}
if (y < 0 || y > extent - 1) {
throw new ServiceException("The Y coordinate is not sane: " + y);
}
// xPos and yPos correspond to the top left hand corner
long[] gridLoc = { x, extent - y - 1, zoomLevel };
return gridLoc;
}
}