/**
* 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.mgmaps;
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 MGMapsConverter extends Service {
public static final String SERVICE_MGMAPS = "mgmaps";
private StorageBroker sb;
private TileLayerDispatcher tld;
private GridSetBroker gsb;
/**
* Protected no-argument constructor to allow run-time instrumentation
*/
protected MGMapsConverter() {
super(SERVICE_MGMAPS);
}
public MGMapsConverter(StorageBroker sb, TileLayerDispatcher tld, GridSetBroker gsb) {
super(SERVICE_MGMAPS);
this.sb = sb;
this.tld = tld;
this.gsb = gsb;
}
public ConveyorTile getConveyor(HttpServletRequest request, HttpServletResponse response)
throws ServiceException {
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 = MGMapsConverter.convert(Integer.parseInt(strZoom),
Integer.parseInt(strX), Integer.parseInt(strY));
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, null, 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
*
* Modified by JaakL for mgmaps zoom understanding: zoom = 17 - zoom
*
* @param quadKey
* @return
*/
public static long[] convert(long zoomLevel, long x, long y) throws ServiceException {
if(zoomLevel > 17) {
throw new ServiceException("Zoomlevel cannot be greater than 17 for Mobile GMaps");
}
// Extent is the total number of tiles in y direction
long newZoom = 17 - zoomLevel;
long extent = (long) Math.pow(2, newZoom);
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, newZoom };
return gridLoc;
}
}