]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/gui/map/OsmMapSource.java
Version 19, May 2018
[GpsPrune.git] / tim / prune / gui / map / OsmMapSource.java
1 package tim.prune.gui.map;
2
3 import java.util.regex.Matcher;
4 import tim.prune.I18nManager;
5
6 /**
7  * Class to provide a map source for all OSM-like sources
8  * (eg mapnik, opencyclemap, openpistemap etc).
9  * These can be single-layer or double-layer sources with tiles
10  * in various formats (default png)
11  */
12 public class OsmMapSource extends MapSource
13 {
14         /** Name for this source */
15         private String _name = null;
16         /** Base urls */
17         private String[] _baseUrls = null;
18         /** Site names */
19         private String[] _siteNames = null;
20         /** Maximum zoom level */
21         private int _maxZoom = 0;
22         /** API key, usually remains empty */
23         private String _apiKey = null;
24
25
26         /**
27          * Constructor giving single name and url
28          * @param inName source name
29          * @param inUrl base url
30          */
31         public OsmMapSource(String inName, String inUrl)
32         {
33                 this(inName, inUrl, "png", null, null, 18);
34         }
35
36         /**
37          * Constructor giving name, two strings and maximum zoom
38          * @param inName source name
39          * @param inStr1 base layer url
40          * @param inStr2 either base layer extension or upper layer url
41          * @param inMaxZoom maximum zoom level
42          */
43         public OsmMapSource(String inName, String inStr1, String inStr2, int inMaxZoom)
44         {
45                 if (inStr2 != null && inStr2.length() == 3)
46                         init(inName, inStr1, inStr2, null, null, inMaxZoom);
47                 else
48                         init(inName, inStr1, "png", inStr2, "png", inMaxZoom);
49         }
50
51         /**
52          * Constructor giving name, urls, extensions and maximum zoom
53          * @param inName source name
54          * @param inUrl1 base layer url
55          * @param inExt1 extension for base layer
56          * @param inUrl2 upper layer url
57          * @param inExt2 extension for top layer
58          * @param inMaxZoom maximum zoom level
59          */
60         public OsmMapSource(String inName, String inUrl1, String inExt1,
61                 String inUrl2, String inExt2, int inMaxZoom)
62         {
63                 init(inName, inUrl1, inExt1, inUrl2, inExt2, inMaxZoom);
64         }
65
66         /**
67          * Initialisation giving name, urls, extensions and maximum zoom
68          * @param inName source name
69          * @param inUrl1 base layer url
70          * @param inExt1 extension for base layer
71          * @param inUrl2 upper layer url
72          * @param inExt2 extension for top layer
73          * @param inMaxZoom maximum zoom level
74          */
75         private void init(String inName, String inUrl1, String inExt1,
76                 String inUrl2, String inExt2, int inMaxZoom)
77         {
78                 _name = inName;
79                 if (_name == null || _name.trim().equals("")) {_name = I18nManager.getText("mapsource.unknown");}
80                 _baseUrls = new String[2];
81                 _baseUrls[0] = fixBaseUrl(inUrl1);
82                 _baseUrls[1] = fixBaseUrl(inUrl2);
83                 _extensions = new String[2];
84                 _extensions[0] = inExt1;
85                 _extensions[1] = inExt2;
86                 _siteNames = new String[2];
87                 _siteNames[0] = fixSiteName(_baseUrls[0]);
88                 _siteNames[1] = fixSiteName(_baseUrls[1]);
89                 // Swap layers if second layer given without first
90                 if (_baseUrls[0] == null && _baseUrls[1] != null)
91                 {
92                         _baseUrls[0] = _baseUrls[1];
93                         _siteNames[0] = _siteNames[1];
94                         _baseUrls[1] = _siteNames[1] = null;
95                 }
96                 _maxZoom = inMaxZoom;
97         }
98
99         /** Set the API key (if required) */
100         public void setApiKey(String inKey)
101         {
102                 _apiKey = inKey;
103         }
104
105         /**
106          * Construct a new map source from its config string
107          * @param inConfigString string from Config, separated by semicolons
108          * @return new map source, or null if not parseable
109          */
110         public static OsmMapSource fromConfig(String inConfigString)
111         {
112                 OsmMapSource source = null;
113                 if (inConfigString.startsWith("o:"))
114                 {
115                         String[] items = inConfigString.substring(2).split(";");
116                         try {
117                                 if (items.length == 3) { // single source url
118                                         source = new OsmMapSource(items[0], items[1], null, Integer.parseInt(items[2]));
119                                 }
120                                 else if (items.length == 4) { // two urls or one url plus extension
121                                         source = new OsmMapSource(items[0], items[1], items[2], Integer.parseInt(items[3]));
122                                 }
123                                 else if (items.length == 6) { // two urls and two extensions
124                                         source = new OsmMapSource(items[0], items[1], items[2], items[3], items[4], Integer.parseInt(items[5]));
125                                 }
126                         } catch (NumberFormatException nfe) {}
127                 }
128                 return source;
129         }
130
131         /**
132          * @return name
133          */
134         public String getName() {
135                 return _name;
136         }
137
138         /** Number of layers */
139         public int getNumLayers() {
140                 return _baseUrls[1] == null?1:2;
141         }
142
143         /** Base url for this source */
144         public String getBaseUrl(int inLayerNum) {
145                 return _baseUrls[inLayerNum];
146         }
147
148         /** site name without protocol or www. */
149         public String getSiteName(int inLayerNum) {
150                 return _siteNames[inLayerNum];
151         }
152
153         /**
154          * Make the URL to get the specified tile
155          */
156         public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
157         {
158                 // Check if the base url has a [1234], if so replace at random
159                 StringBuffer url = new StringBuffer();
160                 url.append(pickServerUrl(_baseUrls[inLayerNum]));
161                 url.append(inZoom).append('/').append(inX).append('/').append(inY);
162                 url.append('.').append(getFileExtension(inLayerNum));
163                 if (_apiKey != null)
164                 {
165                         url.append("?apikey=").append(_apiKey);
166                 }
167                 return url.toString();
168         }
169
170         /**
171          * @return maximum zoom level
172          */
173         public final int getMaxZoomLevel()
174         {
175                 return _maxZoom;
176         }
177
178         /**
179          * If the base url contains something like [1234], then pick a server
180          * @param inBaseUrl base url
181          * @return modified base url
182          */
183         protected static final String pickServerUrl(String inBaseUrl)
184         {
185                 if (inBaseUrl == null || inBaseUrl.indexOf('[') < 0) {
186                         return inBaseUrl;
187                 }
188                 // Check for [.*] (once only)
189                 // Only need to support one, make things a bit easier
190                 final Matcher matcher = WILD_PATTERN.matcher(inBaseUrl);
191                 // if not, return base url unchanged
192                 if (!matcher.matches()) {
193                         return inBaseUrl;
194                 }
195                 // if so, pick one at random and replace in the String
196                 final String match = matcher.group(2);
197                 final int numMatches = match.length();
198                 String server = null;
199                 if (numMatches > 0)
200                 {
201                         int matchNum = (int) Math.floor(Math.random() * numMatches);
202                         server = "" + match.charAt(matchNum);
203                 }
204                 final String result = matcher.group(1) + (server==null?"":server) + matcher.group(3);
205                 return result;
206         }
207
208         /**
209          * @return semicolon-separated list of all fields
210          */
211         public String getConfigString()
212         {
213                 return "o:" +  getName() + ";" + getSiteStrings() + getMaxZoomLevel();
214         }
215 }