source: josm/trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java@ 5369

Last change on this file since 5369 was 5369, checked in by simon04, 12 years ago

Suggest imagery layers for downloaded area based on <bounds>.

  • Property svn:eol-style set to native
File size: 17.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import java.awt.Image;
5import java.util.Arrays;
6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.Collections;
9import java.util.List;
10import java.util.regex.Matcher;
11import java.util.regex.Pattern;
12
13import javax.swing.ImageIcon;
14
15import org.openstreetmap.josm.Main;
16import org.openstreetmap.josm.data.Bounds;
17import org.openstreetmap.josm.data.Preferences.pref;
18import org.openstreetmap.josm.io.OsmApi;
19import org.openstreetmap.josm.tools.CheckParameterUtil;
20import org.openstreetmap.josm.tools.ImageProvider;
21import org.openstreetmap.gui.jmapviewer.Coordinate;
22import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
23import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
24import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
25import org.openstreetmap.josm.tools.CheckParameterUtil;
26
27/**
28 * Class that stores info about an image background layer.
29 *
30 * @author Frederik Ramm <frederik@remote.org>
31 */
32public class ImageryInfo implements Comparable<ImageryInfo>, Attributed {
33
34 public enum ImageryType {
35 WMS("wms"),
36 TMS("tms"),
37 HTML("html"),
38 BING("bing"),
39 SCANEX("scanex");
40
41 private String urlString;
42
43 ImageryType(String urlString) {
44 this.urlString = urlString;
45 }
46
47 public String getUrlString() {
48 return urlString;
49 }
50
51 public static ImageryType fromUrlString(String s) {
52 for (ImageryType type : ImageryType.values()) {
53 if (type.getUrlString().equals(s)) {
54 return type;
55 }
56 }
57 return null;
58 }
59 }
60
61 public static class ImageryBounds extends Bounds {
62 public ImageryBounds(String asString, String separator) {
63 super(asString, separator);
64 }
65
66 private List<Shape> shapes = new ArrayList<Shape>();
67
68 public void addShape(Shape shape) {
69 this.shapes.add(shape);
70 }
71
72 public void setShapes(List<Shape> shapes) {
73 this.shapes = shapes;
74 }
75
76 public List<Shape> getShapes() {
77 return shapes;
78 }
79 }
80
81 private String name;
82 private String url = null;
83 private boolean defaultEntry = false;
84 private String cookies = null;
85 private String eulaAcceptanceRequired= null;
86 private ImageryType imageryType = ImageryType.WMS;
87 private double pixelPerDegree = 0.0;
88 private int defaultMaxZoom = 0;
89 private int defaultMinZoom = 0;
90 private ImageryBounds bounds = null;
91 private List<String> serverProjections;
92 private String attributionText;
93 private String attributionLinkURL;
94 private String attributionImage;
95 private String attributionImageURL;
96 private String termsOfUseText;
97 private String termsOfUseURL;
98 private String countryCode = "";
99 private String icon;
100 // when adding a field, also adapt the ImageryInfo(ImageryInfo) constructor
101
102 /** auxiliary class to save an ImageryInfo object in the preferences */
103 public static class ImageryPreferenceEntry {
104 @pref String name;
105 @pref String type;
106 @pref String url;
107 @pref double pixel_per_eastnorth;
108 @pref String eula;
109 @pref String attribution_text;
110 @pref String attribution_url;
111 @pref String logo_image;
112 @pref String logo_url;
113 @pref String terms_of_use_text;
114 @pref String terms_of_use_url;
115 @pref String country_code = "";
116 @pref int max_zoom;
117 @pref int min_zoom;
118 @pref String cookies;
119 @pref String bounds;
120 @pref String shapes;
121 @pref String projections;
122 @pref String icon;
123
124 public ImageryPreferenceEntry() {
125 }
126
127 public ImageryPreferenceEntry(ImageryInfo i) {
128 name = i.name;
129 type = i.imageryType.getUrlString();
130 url = i.url;
131 pixel_per_eastnorth = i.pixelPerDegree;
132 eula = i.eulaAcceptanceRequired;
133 attribution_text = i.attributionText;
134 attribution_url = i.attributionLinkURL;
135 logo_image = i.attributionImage;
136 logo_url = i.attributionImageURL;
137 terms_of_use_text = i.termsOfUseText;
138 terms_of_use_url = i.termsOfUseURL;
139 country_code = i.countryCode;
140 max_zoom = i.defaultMaxZoom;
141 min_zoom = i.defaultMinZoom;
142 cookies = i.cookies;
143 icon = i.icon;
144 if (i.bounds != null) {
145 bounds = i.bounds.encodeAsString(",");
146 String shapesString = "";
147 for (Shape s : i.bounds.getShapes()) {
148 if (!shapesString.isEmpty()) {
149 shapesString += ";";
150 }
151 shapesString += s.encodeAsString(",");
152 }
153 if (!shapesString.isEmpty()) {
154 shapes = shapesString;
155 }
156 }
157 if (i.serverProjections != null && !i.serverProjections.isEmpty()) {
158 String val = "";
159 for (String p : i.serverProjections) {
160 if (!val.isEmpty())
161 val += ",";
162 val += p;
163 }
164 projections = val;
165 }
166 }
167 }
168
169 public ImageryInfo() {
170 }
171
172 public ImageryInfo(String name) {
173 this.name=name;
174 }
175
176 public ImageryInfo(String name, String url) {
177 this.name=name;
178 setExtendedUrl(url);
179 }
180
181 public ImageryInfo(String name, String url, String eulaAcceptanceRequired) {
182 this.name=name;
183 setExtendedUrl(url);
184 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
185 }
186
187 public ImageryInfo(String name, String url, String eulaAcceptanceRequired, String cookies) {
188 this.name=name;
189 setExtendedUrl(url);
190 this.cookies=cookies;
191 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
192 }
193
194 public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies) {
195 this.name=name;
196 setExtendedUrl(url);
197 ImageryType t = ImageryType.fromUrlString(type);
198 this.cookies=cookies;
199 if (t != null) {
200 this.imageryType = t;
201 }
202 }
203
204 public ImageryInfo(String name, String url, String cookies, double pixelPerDegree) {
205 this.name=name;
206 setExtendedUrl(url);
207 this.cookies=cookies;
208 this.pixelPerDegree=pixelPerDegree;
209 }
210
211 public ImageryInfo(ImageryPreferenceEntry e) {
212 CheckParameterUtil.ensureParameterNotNull(e.name, "name");
213 CheckParameterUtil.ensureParameterNotNull(e.url, "url");
214 name = e.name;
215 url = e.url;
216 cookies = e.cookies;
217 eulaAcceptanceRequired = e.eula;
218 imageryType = ImageryType.fromUrlString(e.type);
219 if (imageryType == null) throw new IllegalArgumentException("unknown type");
220 pixelPerDegree = e.pixel_per_eastnorth;
221 defaultMaxZoom = e.max_zoom;
222 defaultMinZoom = e.min_zoom;
223 if (e.bounds != null) {
224 bounds = new ImageryBounds(e.bounds, ",");
225 if (e.shapes != null) {
226 try {
227 for (String s : e.shapes.split(";")) {
228 bounds.addShape(new Shape(s, ","));
229 }
230 } catch (IllegalArgumentException ex) {
231 Main.warn(ex.toString());
232 }
233 }
234 }
235 if (e.projections != null) {
236 serverProjections = Arrays.asList(e.projections.split(","));
237 }
238 attributionText = e.attribution_text;
239 attributionLinkURL = e.attribution_url;
240 attributionImage = e.logo_image;
241 attributionImageURL = e.logo_url;
242 termsOfUseText = e.terms_of_use_text;
243 termsOfUseURL = e.terms_of_use_url;
244 countryCode = e.country_code;
245 icon = e.icon;
246 }
247
248 public ImageryInfo(ImageryInfo i) {
249 this.name = i.name;
250 this.url = i.url;
251 this.defaultEntry = i.defaultEntry;
252 this.cookies = i.cookies;
253 this.eulaAcceptanceRequired = null;
254 this.imageryType = i.imageryType;
255 this.pixelPerDegree = i.pixelPerDegree;
256 this.defaultMaxZoom = i.defaultMaxZoom;
257 this.defaultMinZoom = i.defaultMinZoom;
258 this.bounds = i.bounds;
259 this.serverProjections = i.serverProjections;
260 this.attributionText = i.attributionText;
261 this.attributionLinkURL = i.attributionLinkURL;
262 this.attributionImage = i.attributionImage;
263 this.attributionImageURL = i.attributionImageURL;
264 this.termsOfUseText = i.termsOfUseText;
265 this.termsOfUseURL = i.termsOfUseURL;
266 this.countryCode = i.countryCode;
267 this.icon = i.icon;
268 }
269
270 @Override
271 public boolean equals(Object o) {
272 if (this == o) return true;
273 if (o == null || getClass() != o.getClass()) return false;
274
275 ImageryInfo that = (ImageryInfo) o;
276
277 if (imageryType != that.imageryType) return false;
278 if (url != null ? !url.equals(that.url) : that.url != null) return false;
279
280 return true;
281 }
282
283 @Override
284 public int hashCode() {
285 int result = url != null ? url.hashCode() : 0;
286 result = 31 * result + (imageryType != null ? imageryType.hashCode() : 0);
287 return result;
288 }
289
290 @Override
291 public String toString() {
292 return "ImageryInfo{" +
293 "name='" + name + '\'' +
294 ", countryCode='" + countryCode + '\'' +
295 ", url='" + url + '\'' +
296 ", imageryType=" + imageryType +
297 '}';
298 }
299
300 @Override
301 public int compareTo(ImageryInfo in)
302 {
303 int i = countryCode.compareTo(in.countryCode);
304 if (i == 0) {
305 i = name.compareTo(in.name);
306 }
307 if (i == 0) {
308 i = url.compareTo(in.url);
309 }
310 if (i == 0) {
311 i = Double.compare(pixelPerDegree, in.pixelPerDegree);
312 }
313 return i;
314 }
315
316 public boolean equalsBaseValues(ImageryInfo in)
317 {
318 return url.equals(in.url);
319 }
320
321 public void setPixelPerDegree(double ppd) {
322 this.pixelPerDegree = ppd;
323 }
324
325 public void setDefaultMaxZoom(int defaultMaxZoom) {
326 this.defaultMaxZoom = defaultMaxZoom;
327 }
328
329 public void setDefaultMinZoom(int defaultMinZoom) {
330 this.defaultMinZoom = defaultMinZoom;
331 }
332
333 public void setBounds(ImageryBounds b) {
334 this.bounds = b;
335 }
336
337 public ImageryBounds getBounds() {
338 return bounds;
339 }
340
341 @Override
342 public boolean requiresAttribution() {
343 return attributionText != null || attributionImage != null || termsOfUseText != null || termsOfUseURL != null;
344 }
345
346 @Override
347 public String getAttributionText(int zoom, Coordinate topLeft, Coordinate botRight) {
348 return attributionText;
349 }
350
351 @Override
352 public String getAttributionLinkURL() {
353 return attributionLinkURL;
354 }
355
356 @Override
357 public Image getAttributionImage() {
358 ImageIcon i = ImageProvider.getIfAvailable(attributionImage);
359 if (i != null) {
360 return i.getImage();
361 }
362 return null;
363 }
364
365 @Override
366 public String getAttributionImageURL() {
367 return attributionImageURL;
368 }
369
370 @Override
371 public String getTermsOfUseText() {
372 return termsOfUseText;
373 }
374
375 @Override
376 public String getTermsOfUseURL() {
377 return termsOfUseURL;
378 }
379
380 public void setAttributionText(String text) {
381 attributionText = text;
382 }
383
384 public void setAttributionImageURL(String text) {
385 attributionImageURL = text;
386 }
387
388 public void setAttributionImage(String text) {
389 attributionImage = text;
390 }
391
392 public void setAttributionLinkURL(String text) {
393 attributionLinkURL = text;
394 }
395
396 public void setTermsOfUseText(String text) {
397 termsOfUseText = text;
398 }
399
400 public void setTermsOfUseURL(String text) {
401 termsOfUseURL = text;
402 }
403
404 public void setExtendedUrl(String url) {
405 CheckParameterUtil.ensureParameterNotNull(url);
406
407 // Default imagery type is WMS
408 this.url = url;
409 this.imageryType = ImageryType.WMS;
410
411 defaultMaxZoom = 0;
412 defaultMinZoom = 0;
413 for (ImageryType type : ImageryType.values()) {
414 Matcher m = Pattern.compile(type.getUrlString()+"(?:\\[(?:(\\d+),)?(\\d+)\\])?:(.*)").matcher(url);
415 if(m.matches()) {
416 this.url = m.group(3);
417 this.imageryType = type;
418 if(m.group(2) != null) {
419 defaultMaxZoom = Integer.valueOf(m.group(2));
420 }
421 if(m.group(1) != null) {
422 defaultMinZoom = Integer.valueOf(m.group(1));
423 }
424 break;
425 }
426 }
427
428 if(serverProjections == null || serverProjections.isEmpty()) {
429 try {
430 serverProjections = new ArrayList<String>();
431 Matcher m = Pattern.compile(".*\\{PROJ\\(([^)}]+)\\)\\}.*").matcher(url.toUpperCase());
432 if(m.matches()) {
433 for(String p : m.group(1).split(","))
434 serverProjections.add(p);
435 }
436 } catch(Exception e) {
437 }
438 }
439 }
440
441 public String getName() {
442 return this.name;
443 }
444
445 public void setName(String name) {
446 this.name = name;
447 }
448
449 public String getUrl() {
450 return this.url;
451 }
452
453 public void setUrl(String url) {
454 this.url = url;
455 }
456
457 public boolean isDefaultEntry() {
458 return defaultEntry;
459 }
460
461 public void setDefaultEntry(boolean defaultEntry) {
462 this.defaultEntry = defaultEntry;
463 }
464
465 public String getCookies() {
466 return this.cookies;
467 }
468
469 public double getPixelPerDegree() {
470 return this.pixelPerDegree;
471 }
472
473 public int getMaxZoom() {
474 return this.defaultMaxZoom;
475 }
476
477 public int getMinZoom() {
478 return this.defaultMinZoom;
479 }
480
481 public String getEulaAcceptanceRequired() {
482 return eulaAcceptanceRequired;
483 }
484
485 public void setEulaAcceptanceRequired(String eulaAcceptanceRequired) {
486 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
487 }
488
489 public String getCountryCode() {
490 return countryCode;
491 }
492
493 public void setCountryCode(String countryCode) {
494 this.countryCode = countryCode;
495 }
496
497 public String getIcon() {
498 return icon;
499 }
500
501 public void setIcon(String icon) {
502 this.icon = icon;
503 }
504
505 /**
506 * Get the projections supported by the server. Only relevant for
507 * WMS-type ImageryInfo at the moment.
508 * @return null, if no projections have been specified; the list
509 * of supported projections otherwise.
510 */
511 public List<String> getServerProjections() {
512 if (serverProjections == null)
513 return Collections.emptyList();
514 return Collections.unmodifiableList(serverProjections);
515 }
516
517 public void setServerProjections(Collection<String> serverProjections) {
518 this.serverProjections = new ArrayList<String>(serverProjections);
519 }
520
521 public String getExtendedUrl() {
522 return imageryType.getUrlString() + (defaultMaxZoom != 0
523 ? "["+(defaultMinZoom != 0 ? defaultMinZoom+",":"")+defaultMaxZoom+"]" : "") + ":" + url;
524 }
525
526 public String getToolbarName()
527 {
528 String res = name;
529 if(pixelPerDegree != 0.0) {
530 res += "#PPD="+pixelPerDegree;
531 }
532 return res;
533 }
534
535 public String getMenuName()
536 {
537 String res = name;
538 if(pixelPerDegree != 0.0) {
539 res += " ("+pixelPerDegree+")";
540 }
541 return res;
542 }
543
544 public boolean hasAttribution()
545 {
546 return attributionText != null;
547 }
548
549 public void copyAttribution(ImageryInfo i)
550 {
551 this.attributionImage = i.attributionImage;
552 this.attributionImageURL = i.attributionImageURL;
553 this.attributionText = i.attributionText;
554 this.attributionLinkURL = i.attributionLinkURL;
555 this.termsOfUseText = i.termsOfUseText;
556 this.termsOfUseURL = i.termsOfUseURL;
557 }
558
559 /**
560 * Applies the attribution from this object to a TMSTileSource.
561 */
562 public void setAttribution(AbstractTileSource s) {
563 if (attributionText != null) {
564 if (attributionText.equals("osm")) {
565 s.setAttributionText(new Mapnik().getAttributionText(0, null, null));
566 } else {
567 s.setAttributionText(attributionText);
568 }
569 }
570 if (attributionLinkURL != null) {
571 if (attributionLinkURL.equals("osm")) {
572 s.setAttributionLinkURL(new Mapnik().getAttributionLinkURL());
573 } else {
574 s.setAttributionLinkURL(attributionLinkURL);
575 }
576 }
577 if (attributionImage != null) {
578 ImageIcon i = ImageProvider.getIfAvailable(null, attributionImage);
579 if (i != null) {
580 s.setAttributionImage(i.getImage());
581 }
582 }
583 if (attributionImageURL != null) {
584 s.setAttributionImageURL(attributionImageURL);
585 }
586 if (termsOfUseText != null) {
587 s.setTermsOfUseText(termsOfUseText);
588 }
589 if (termsOfUseURL != null) {
590 if (termsOfUseURL.equals("osm")) {
591 s.setTermsOfUseURL(new Mapnik().getTermsOfUseURL());
592 } else {
593 s.setTermsOfUseURL(termsOfUseURL);
594 }
595 }
596 }
597
598 public ImageryType getImageryType() {
599 return imageryType;
600 }
601
602 public void setImageryType(ImageryType imageryType) {
603 this.imageryType = imageryType;
604 }
605
606 /**
607 * Returns true if this layer's URL is matched by one of the regular
608 * expressions kept by the current OsmApi instance.
609 */
610 public boolean isBlacklisted() {
611 return OsmApi.getOsmApi().getCapabilities().isOnImageryBlacklist(this.url);
612 }
613}
Note: See TracBrowser for help on using the repository browser.