001    package org.openstreetmap.gui.jmapviewer.tilesources;
002    
003    import java.util.Map;
004    import java.util.HashMap;
005    import java.util.Random;
006    import java.util.regex.Pattern;
007    import java.util.regex.Matcher;
008    
009    public 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    }