org.geowebcache.service.ve.VEConverter.java Source code

Java tutorial

Introduction

Here is the source code for org.geowebcache.service.ve.VEConverter.java

Source

/**
 * 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.ve;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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 Virtual Earth quad keys to the internal representation
 * of a tile.
 */
public class VEConverter extends Service {
    public static final String SERVICE_VE = "ve";

    private static Log log = LogFactory.getLog(org.geowebcache.service.ve.VEConverter.class);

    private StorageBroker sb;

    private TileLayerDispatcher tld;

    private GridSetBroker gsb;

    /**
     * Protected no-argument constructor to allow run-time instrumentation
     */
    protected VEConverter() {
        super(SERVICE_VE);
    }

    public VEConverter(StorageBroker sb, TileLayerDispatcher tld, GridSetBroker gsb) {
        super(SERVICE_VE);
        this.sb = sb;
        this.tld = tld;
        this.gsb = gsb;
    }

    public ConveyorTile getConveyor(HttpServletRequest request, HttpServletResponse response)
            throws ServiceException {
        Map<String, String[]> params = request.getParameterMap();

        String layerId = super.getLayersParameter(request);

        String encoding = request.getCharacterEncoding();

        String strQuadKey = ServletUtils.stringFromMap(params, encoding, "quadkey");
        String strFormat = ServletUtils.stringFromMap(params, encoding, "format");
        String strCached = ServletUtils.stringFromMap(params, encoding, "cached");
        String strMetaTiled = ServletUtils.stringFromMap(params, encoding, "metatiled");

        long[] gridLoc = VEConverter.convert(strQuadKey);

        MimeType mimeType = null;
        if (strFormat != null) {
            try {
                mimeType = MimeType.createFromFormat(strFormat);
            } catch (MimeException me) {
                throw new ServiceException("Unable to determined 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 a quadkey into the internal representation {x,y,z} of a grid
     * location
     * 
     * @param quadKey
     * @return internal representation
     */
    public static long[] convert(String strQuadKey) {
        char[] quadArray = strQuadKey.toCharArray();

        long zoomLevel = quadArray.length;

        long extent = (long) Math.pow(2, zoomLevel);
        long yPos = 0;
        long xPos = 0;

        // Now we traverse the quadArray from left to right, interpretation
        // 0 1
        // 2 3
        // see http://msdn2.microsoft.com/en-us/library/bb259689.aspx
        //
        // What we'll end up with is the top left hand corner of the bbox
        //
        for (int i = 0; i < zoomLevel; i++) {
            char curChar = quadArray[i];

            // For each round half as much is at stake
            extent = extent / 2;

            if (curChar == '0') {
                // X stays
                yPos += extent;
            } else if (curChar == '1') {
                xPos += extent;
                yPos += extent;
            } else if (curChar == '2') {
                // X stays
                // Y stays
            } else if (curChar == '3') {
                xPos += extent;
                // Y stays
            } else {
                log.error("Don't know how to interpret quadKey: " + strQuadKey);
                return null;
            }
        }

        long[] gridLoc = { xPos, yPos, zoomLevel };

        return gridLoc;
    }
}