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}