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

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

see #7182 - Individual Icons for Imagery Background

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