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