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