001package org.openstreetmap.gui.jmapviewer.tilesources;
002
003import java.util.Map;
004import java.util.HashMap;
005import java.util.Random;
006import java.util.regex.Pattern;
007import java.util.regex.Matcher;
008
009public class TemplatedTMSTileSource extends TMSTileSource {
010
011    private Random rand = null;
012    private String[] randomParts = null;
013    private Map<String, String> headers = new HashMap<String, String>();
014
015    public static final String PATTERN_ZOOM    = "\\{(?:(\\d+)-)?zoom([+-]\\d+)?\\}";
016    public static final String PATTERN_X       = "\\{x\\}";
017    public static final String PATTERN_Y       = "\\{y\\}";
018    public static final String PATTERN_Y_YAHOO = "\\{!y\\}";
019    public static final String PATTERN_NEG_Y   = "\\{-y\\}";
020    public static final String PATTERN_SWITCH  = "\\{switch:([^}]+)\\}";
021    public static final String PATTERN_HEADER  = "\\{header\\(([^,]+),([^}]+)\\)\\}";
022
023    public static final String[] ALL_PATTERNS = {
024        PATTERN_HEADER, PATTERN_ZOOM, PATTERN_X, PATTERN_Y, PATTERN_Y_YAHOO, PATTERN_NEG_Y,
025        PATTERN_SWITCH
026    };
027
028    public TemplatedTMSTileSource(String name, String url, int maxZoom) {
029        super(name, url, maxZoom);
030        handleTemplate();
031    }
032
033    public TemplatedTMSTileSource(String name, String url, int minZoom, int maxZoom) {
034        super(name, url, minZoom, maxZoom);
035        handleTemplate();
036    }
037
038    private void handleTemplate() {
039        // Capturing group pattern on switch values
040        Matcher m = Pattern.compile(".*"+PATTERN_SWITCH+".*").matcher(baseUrl);
041        if (m.matches()) {
042            rand = new Random();
043            randomParts = m.group(1).split(",");
044        }
045        Pattern pattern = Pattern.compile(PATTERN_HEADER);
046        StringBuffer output = new StringBuffer();
047        Matcher matcher = pattern.matcher(baseUrl);
048        while (matcher.find()) {
049            headers.put(matcher.group(1),matcher.group(2));
050            matcher.appendReplacement(output, "");
051        }
052        matcher.appendTail(output);
053        baseUrl = output.toString();
054    }
055
056    public Map<String, String> getHeaders() {
057        return headers;
058    }
059
060    @Override
061    public String getTileUrl(int zoom, int tilex, int tiley) {
062        int finalZoom = zoom;
063        Matcher m = Pattern.compile(".*"+PATTERN_ZOOM+".*").matcher(this.baseUrl);
064        if (m.matches()) {
065            if(m.group(1) != null) {
066                finalZoom = Integer.valueOf(m.group(1))-zoom;
067            }
068            if(m.group(2) != null) {
069                String ofs = m.group(2);
070                if(ofs.startsWith("+"))
071                    ofs = ofs.substring(1);
072                finalZoom += Integer.valueOf(ofs);
073            }
074        }
075        String r = this.baseUrl
076            .replaceAll(PATTERN_ZOOM, Integer.toString(finalZoom))
077            .replaceAll(PATTERN_X, Integer.toString(tilex))
078            .replaceAll(PATTERN_Y, Integer.toString(tiley))
079            .replaceAll(PATTERN_Y_YAHOO, Integer.toString((int)Math.pow(2, zoom-1)-1-tiley))
080            .replaceAll(PATTERN_NEG_Y, Integer.toString((int)Math.pow(2, zoom)-1-tiley));
081        if (rand != null) {
082            r = r.replaceAll(PATTERN_SWITCH, randomParts[rand.nextInt(randomParts.length)]);
083        }
084        return r;
085    }
086}