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

Last change on this file since 9134 was 9134, checked in by wiktorn, 8 years ago

Introduce imagery-source warnings about alignment and reprojections.

Introduce new setting to maps.xsd:

  • valid-georeference - which marks imagery sources that are properly georeferenced (i.e. do not need imagery offset adjustments)
  • epsg4326to3857Supported - which marks imagery sources that might be safely queried using EPSG:3857 square BBOX, using EPSG:4326 projection

Make the AlignImageryPanel to show only, when valid-georeference is not set to true and provide the ability to hide this message ("do not show again"), which will be now remembered on per-source basis. Due to this changes, good imagery sources will not show warning to novice users and - experienced users will be presented with a warning, when they open an new imagery source which might be unaligned.

Introduce the ability to check "do not show again" the warning about EPSG:3857 to EPSG:4326 reprojections - as above - on per imagery basis.

All imagery sources should be now reviewed and set valid-georeference=true when appropriate.

  • Property svn:eol-style set to native
File size: 33.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.imagery;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Image;
7import java.util.ArrayList;
8import java.util.Arrays;
9import java.util.Collection;
10import java.util.Collections;
11import java.util.List;
12import java.util.Locale;
13import java.util.Map;
14import java.util.Objects;
15import java.util.TreeSet;
16import java.util.regex.Matcher;
17import java.util.regex.Pattern;
18
19import javax.swing.ImageIcon;
20
21import org.openstreetmap.gui.jmapviewer.OsmMercator;
22import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
23import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
24import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
25import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
26import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo;
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.data.Bounds;
29import org.openstreetmap.josm.data.Preferences.pref;
30import org.openstreetmap.josm.io.Capabilities;
31import org.openstreetmap.josm.io.OsmApi;
32import org.openstreetmap.josm.tools.CheckParameterUtil;
33import org.openstreetmap.josm.tools.ImageProvider;
34import org.openstreetmap.josm.tools.LanguageInfo;
35
36/**
37 * Class that stores info about an image background layer.
38 *
39 * @author Frederik Ramm
40 */
41public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInfo>, Attributed {
42
43 /**
44 * Type of imagery entry.
45 */
46 public enum ImageryType {
47 /** A WMS (Web Map Service) entry. **/
48 WMS("wms"),
49 /** A TMS (Tile Map Service) entry. **/
50 TMS("tms"),
51 /** An HTML proxy (previously used for Yahoo imagery) entry. **/
52 HTML("html"),
53 /** TMS entry for Microsoft Bing. */
54 BING("bing"),
55 /** TMS entry for Russian company <a href="https://wiki.openstreetmap.org/wiki/WikiProject_Russia/kosmosnimki">ScanEx</a>. **/
56 SCANEX("scanex"),
57 /** A WMS endpoint entry only stores the WMS server info, without layer, which are chosen later by the user. **/
58 WMS_ENDPOINT("wms_endpoint"),
59 /** WMTS stores GetCapabilities URL. Does not store any information about the layer **/
60 WMTS("wmts");
61
62
63 private final String typeString;
64
65 ImageryType(String urlString) {
66 this.typeString = urlString;
67 }
68
69 /**
70 * Returns the unique string identifying this type.
71 * @return the unique string identifying this type
72 * @since 6690
73 */
74 public final String getTypeString() {
75 return typeString;
76 }
77
78 /**
79 * Returns the imagery type from the given type string.
80 * @param s The type string
81 * @return the imagery type matching the given type string
82 */
83 public static ImageryType fromString(String s) {
84 for (ImageryType type : ImageryType.values()) {
85 if (type.getTypeString().equals(s)) {
86 return type;
87 }
88 }
89 return null;
90 }
91 }
92
93 /**
94 * Multi-polygon bounds for imagery backgrounds.
95 * Used to display imagery coverage in preferences and to determine relevant imagery entries based on edit location.
96 */
97 public static class ImageryBounds extends Bounds {
98
99 /**
100 * Constructs a new {@code ImageryBounds} from string.
101 * @param asString The string containing the list of shapes defining this bounds
102 * @param separator The shape separator in the given string, usually a comma
103 */
104 public ImageryBounds(String asString, String separator) {
105 super(asString, separator);
106 }
107
108 private List<Shape> shapes = new ArrayList<>();
109
110 /**
111 * Adds a new shape to this bounds.
112 * @param shape The shape to add
113 */
114 public final void addShape(Shape shape) {
115 this.shapes.add(shape);
116 }
117
118 /**
119 * Sets the list of shapes defining this bounds.
120 * @param shapes The list of shapes defining this bounds.
121 */
122 public final void setShapes(List<Shape> shapes) {
123 this.shapes = shapes;
124 }
125
126 /**
127 * Returns the list of shapes defining this bounds.
128 * @return The list of shapes defining this bounds
129 */
130 public final List<Shape> getShapes() {
131 return shapes;
132 }
133
134 @Override
135 public int hashCode() {
136 final int prime = 31;
137 int result = super.hashCode();
138 result = prime * result + ((shapes == null) ? 0 : shapes.hashCode());
139 return result;
140 }
141
142 @Override
143 public boolean equals(Object obj) {
144 if (this == obj)
145 return true;
146 if (!super.equals(obj))
147 return false;
148 if (getClass() != obj.getClass())
149 return false;
150 ImageryBounds other = (ImageryBounds) obj;
151 if (shapes == null) {
152 if (other.shapes != null)
153 return false;
154 } else if (!shapes.equals(other.shapes))
155 return false;
156 return true;
157 }
158 }
159
160
161 /** original name of the imagery entry in case of translation call, for multiple languages English when possible */
162 private String origName;
163 /** (original) language of the translated name entry */
164 private String langName;
165 /** whether this is a entry activated by default or not */
166 private boolean defaultEntry;
167 /** The data part of HTTP cookies header in case the service requires cookies to work */
168 private String cookies;
169 /** Whether this service requires a explicit EULA acceptance before it can be activated */
170 private String eulaAcceptanceRequired;
171 /** type of the imagery servics - WMS, TMS, ... */
172 private ImageryType imageryType = ImageryType.WMS;
173 private double pixelPerDegree;
174 /** maximum zoom level for TMS imagery */
175 private int defaultMaxZoom;
176 /** minimum zoom level for TMS imagery */
177 private int defaultMinZoom;
178 /** display bounds of imagery, displayed in prefs and used for automatic imagery selection */
179 private ImageryBounds bounds;
180 /** projections supported by WMS servers */
181 private List<String> serverProjections;
182 /** description of the imagery entry, should contain notes what type of data it is */
183 private String description;
184 /** language of the description entry */
185 private String langDescription;
186 /** Text of a text attribution displayed when using the imagery */
187 private String attributionText;
188 /** Link behing the text attribution displayed when using the imagery */
189 private String attributionLinkURL;
190 /** Image of a graphical attribution displayed when using the imagery */
191 private String attributionImage;
192 /** Link behind the graphical attribution displayed when using the imagery */
193 private String attributionImageURL;
194 /** Text with usage terms displayed when using the imagery */
195 private String termsOfUseText;
196 /** Link behind the text with usage terms displayed when using the imagery */
197 private String termsOfUseURL;
198 /** country code of the imagery (for country specific imagery) */
199 private String countryCode = "";
200 /** icon used in menu */
201 private String icon;
202 private boolean isGeoreferenceValid = false;
203 private boolean isEpsg4326To3857Supported = false;
204 // when adding a field, also adapt the ImageryInfo(ImageryInfo) and ImageryInfo(ImageryPreferenceEntry) constructor, equals method, and ImageryPreferenceEntry
205
206 /**
207 * Auxiliary class to save an {@link ImageryInfo} object in the preferences.
208 */
209 public static class ImageryPreferenceEntry {
210 @pref String name;
211 @pref String id;
212 @pref String type;
213 @pref String url;
214 @pref double pixel_per_eastnorth;
215 @pref String eula;
216 @pref String attribution_text;
217 @pref String attribution_url;
218 @pref String logo_image;
219 @pref String logo_url;
220 @pref String terms_of_use_text;
221 @pref String terms_of_use_url;
222 @pref String country_code = "";
223 @pref int max_zoom;
224 @pref int min_zoom;
225 @pref String cookies;
226 @pref String bounds;
227 @pref String shapes;
228 @pref String projections;
229 @pref String icon;
230 @pref String description;
231 @pref Map<String, String> noTileHeaders;
232 @pref int tileSize = OsmMercator.DEFAUL_TILE_SIZE;
233 @pref Map<String, String> metadataHeaders;
234 @pref boolean valid_georeference;
235 @pref boolean supports_epsg_4326_to_3857_conversion;
236
237 /**
238 * Constructs a new empty WMS {@code ImageryPreferenceEntry}.
239 */
240 public ImageryPreferenceEntry() {
241 }
242
243 /**
244 * Constructs a new {@code ImageryPreferenceEntry} from a given {@code ImageryInfo}.
245 * @param i The corresponding imagery info
246 */
247 public ImageryPreferenceEntry(ImageryInfo i) {
248 name = i.name;
249 id = i.id;
250 type = i.imageryType.getTypeString();
251 url = i.url;
252 pixel_per_eastnorth = i.pixelPerDegree;
253 eula = i.eulaAcceptanceRequired;
254 attribution_text = i.attributionText;
255 attribution_url = i.attributionLinkURL;
256 logo_image = i.attributionImage;
257 logo_url = i.attributionImageURL;
258 terms_of_use_text = i.termsOfUseText;
259 terms_of_use_url = i.termsOfUseURL;
260 country_code = i.countryCode;
261 max_zoom = i.defaultMaxZoom;
262 min_zoom = i.defaultMinZoom;
263 cookies = i.cookies;
264 icon = i.icon;
265 description = i.description;
266 if (i.bounds != null) {
267 bounds = i.bounds.encodeAsString(",");
268 StringBuilder shapesString = new StringBuilder();
269 for (Shape s : i.bounds.getShapes()) {
270 if (shapesString.length() > 0) {
271 shapesString.append(';');
272 }
273 shapesString.append(s.encodeAsString(","));
274 }
275 if (shapesString.length() > 0) {
276 shapes = shapesString.toString();
277 }
278 }
279 if (i.serverProjections != null && !i.serverProjections.isEmpty()) {
280 StringBuilder val = new StringBuilder();
281 for (String p : i.serverProjections) {
282 if (val.length() > 0) {
283 val.append(',');
284 }
285 val.append(p);
286 }
287 projections = val.toString();
288 }
289 if (i.noTileHeaders != null && !i.noTileHeaders.isEmpty()) {
290 noTileHeaders = i.noTileHeaders;
291 }
292
293 if (i.metadataHeaders != null && !i.metadataHeaders.isEmpty()) {
294 metadataHeaders = i.metadataHeaders;
295 }
296
297 tileSize = i.getTileSize();
298
299 valid_georeference = i.isGeoreferenceValid();
300 supports_epsg_4326_to_3857_conversion = i.isEpsg4326To3857Supported();
301
302 }
303
304 @Override
305 public String toString() {
306 StringBuilder s = new StringBuilder("ImageryPreferenceEntry [name=").append(name);
307 if (id != null) {
308 s.append(" id=").append(id);
309 }
310 s.append(']');
311 return s.toString();
312 }
313 }
314
315 /**
316 * Constructs a new WMS {@code ImageryInfo}.
317 */
318 public ImageryInfo() {
319 super();
320 }
321
322 /**
323 * Constructs a new WMS {@code ImageryInfo} with a given name.
324 * @param name The entry name
325 */
326 public ImageryInfo(String name) {
327 super(name);
328 }
329
330 /**
331 * Constructs a new WMS {@code ImageryInfo} with given name and extended URL.
332 * @param name The entry name
333 * @param url The entry extended URL
334 */
335 public ImageryInfo(String name, String url) {
336 this(name);
337 setExtendedUrl(url);
338 }
339
340 /**
341 * Constructs a new WMS {@code ImageryInfo} with given name, extended and EULA URLs.
342 * @param name The entry name
343 * @param url The entry URL
344 * @param eulaAcceptanceRequired The EULA URL
345 */
346 public ImageryInfo(String name, String url, String eulaAcceptanceRequired) {
347 this(name);
348 setExtendedUrl(url);
349 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
350 }
351
352 /**
353 * Constructs a new {@code ImageryInfo} with given name, url, extended and EULA URLs.
354 * @param name The entry name
355 * @param url The entry URL
356 * @param type The entry imagery type. If null, WMS will be used as default
357 * @param eulaAcceptanceRequired The EULA URL
358 * @param cookies The data part of HTTP cookies header in case the service requires cookies to work
359 * @throws IllegalArgumentException if type refers to an unknown imagery type
360 */
361 public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies) {
362 this(name);
363 setExtendedUrl(url);
364 ImageryType t = ImageryType.fromString(type);
365 this.cookies = cookies;
366 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
367 if (t != null) {
368 this.imageryType = t;
369 } else if (type != null && !type.trim().isEmpty()) {
370 throw new IllegalArgumentException("unknown type: "+type);
371 }
372 }
373
374 public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies, String id) {
375 this(name, url, type, eulaAcceptanceRequired, cookies);
376 setId(id);
377 }
378
379 /**
380 * Constructs a new {@code ImageryInfo} from an imagery preference entry.
381 * @param e The imagery preference entry
382 */
383 public ImageryInfo(ImageryPreferenceEntry e) {
384 super(e.name, e.url, e.id);
385 CheckParameterUtil.ensureParameterNotNull(e.name, "name");
386 CheckParameterUtil.ensureParameterNotNull(e.url, "url");
387 description = e.description;
388 cookies = e.cookies;
389 eulaAcceptanceRequired = e.eula;
390 imageryType = ImageryType.fromString(e.type);
391 if (imageryType == null) throw new IllegalArgumentException("unknown type");
392 pixelPerDegree = e.pixel_per_eastnorth;
393 defaultMaxZoom = e.max_zoom;
394 defaultMinZoom = e.min_zoom;
395 if (e.bounds != null) {
396 bounds = new ImageryBounds(e.bounds, ",");
397 if (e.shapes != null) {
398 try {
399 for (String s : e.shapes.split(";")) {
400 bounds.addShape(new Shape(s, ","));
401 }
402 } catch (IllegalArgumentException ex) {
403 Main.warn(ex);
404 }
405 }
406 }
407 if (e.projections != null) {
408 serverProjections = Arrays.asList(e.projections.split(","));
409 }
410 attributionText = e.attribution_text;
411 attributionLinkURL = e.attribution_url;
412 attributionImage = e.logo_image;
413 attributionImageURL = e.logo_url;
414 termsOfUseText = e.terms_of_use_text;
415 termsOfUseURL = e.terms_of_use_url;
416 countryCode = e.country_code;
417 icon = e.icon;
418 if (e.noTileHeaders != null) {
419 noTileHeaders = e.noTileHeaders;
420 }
421 setTileSize(e.tileSize);
422 metadataHeaders = e.metadataHeaders;
423 isEpsg4326To3857Supported = e.supports_epsg_4326_to_3857_conversion;
424 isGeoreferenceValid = e.valid_georeference;
425 }
426
427 /**
428 * Constructs a new {@code ImageryInfo} from an existing one.
429 * @param i The other imagery info
430 */
431 public ImageryInfo(ImageryInfo i) {
432 super(i.name, i.url, i.id);
433 this.defaultEntry = i.defaultEntry;
434 this.cookies = i.cookies;
435 this.eulaAcceptanceRequired = null;
436 this.imageryType = i.imageryType;
437 this.pixelPerDegree = i.pixelPerDegree;
438 this.defaultMaxZoom = i.defaultMaxZoom;
439 this.defaultMinZoom = i.defaultMinZoom;
440 this.bounds = i.bounds;
441 this.serverProjections = i.serverProjections;
442 this.attributionText = i.attributionText;
443 this.attributionLinkURL = i.attributionLinkURL;
444 this.attributionImage = i.attributionImage;
445 this.attributionImageURL = i.attributionImageURL;
446 this.termsOfUseText = i.termsOfUseText;
447 this.termsOfUseURL = i.termsOfUseURL;
448 this.countryCode = i.countryCode;
449 this.icon = i.icon;
450 this.description = i.description;
451 this.noTileHeaders = i.noTileHeaders;
452 this.metadataHeaders = i.metadataHeaders;
453 this.isEpsg4326To3857Supported = i.isEpsg4326To3857Supported;
454 this.isGeoreferenceValid = i.isGeoreferenceValid;
455 }
456
457 @Override
458 public boolean equals(Object o) {
459 if (this == o) return true;
460 if (o == null || getClass() != o.getClass()) return false;
461
462 ImageryInfo that = (ImageryInfo) o;
463
464 if (imageryType != that.imageryType) return false;
465 if (url != null ? !url.equals(that.url) : that.url != null) return false;
466 if (name != null ? !name.equals(that.name) : that.name != null) return false;
467
468 return true;
469 }
470
471 /**
472 * Check if this object equals another ImageryInfo with respect to the properties
473 * that get written to the preference file.
474 *
475 * The field {@link #pixelPerDegree} is ignored.
476 *
477 * @param other the ImageryInfo object to compare to
478 * @return true if they are equal
479 */
480 public boolean equalsPref(ImageryInfo other) {
481 if (other == null) {
482 return false;
483 }
484
485 return
486 Objects.equals(this.name, other.name) &&
487 Objects.equals(this.id, other.id) &&
488 Objects.equals(this.url, other.url) &&
489 Objects.equals(this.cookies, other.cookies) &&
490 Objects.equals(this.eulaAcceptanceRequired, other.eulaAcceptanceRequired) &&
491 Objects.equals(this.imageryType, other.imageryType) &&
492 Objects.equals(this.defaultMaxZoom, other.defaultMaxZoom) &&
493 Objects.equals(this.defaultMinZoom, other.defaultMinZoom) &&
494 Objects.equals(this.bounds, other.bounds) &&
495 Objects.equals(this.serverProjections, other.serverProjections) &&
496 Objects.equals(this.attributionText, other.attributionText) &&
497 Objects.equals(this.attributionLinkURL, other.attributionLinkURL) &&
498 Objects.equals(this.attributionImageURL, other.attributionImageURL) &&
499 Objects.equals(this.attributionImage, other.attributionImage) &&
500 Objects.equals(this.termsOfUseText, other.termsOfUseText) &&
501 Objects.equals(this.termsOfUseURL, other.termsOfUseURL) &&
502 Objects.equals(this.countryCode, other.countryCode) &&
503 Objects.equals(this.icon, other.icon) &&
504 Objects.equals(this.description, other.description) &&
505 Objects.equals(this.noTileHeaders, other.noTileHeaders) &&
506 Objects.equals(this.metadataHeaders, other.metadataHeaders);
507 }
508
509 @Override
510 public int hashCode() {
511 int result = url != null ? url.hashCode() : 0;
512 result = 31 * result + (imageryType != null ? imageryType.hashCode() : 0);
513 return result;
514 }
515
516 @Override
517 public String toString() {
518 return "ImageryInfo{" +
519 "name='" + name + '\'' +
520 ", countryCode='" + countryCode + '\'' +
521 ", url='" + url + '\'' +
522 ", imageryType=" + imageryType +
523 '}';
524 }
525
526 @Override
527 public int compareTo(ImageryInfo in) {
528 int i = countryCode.compareTo(in.countryCode);
529 if (i == 0) {
530 i = name.toLowerCase(Locale.ENGLISH).compareTo(in.name.toLowerCase(Locale.ENGLISH));
531 }
532 if (i == 0) {
533 i = url.compareTo(in.url);
534 }
535 if (i == 0) {
536 i = Double.compare(pixelPerDegree, in.pixelPerDegree);
537 }
538 return i;
539 }
540
541 public boolean equalsBaseValues(ImageryInfo in) {
542 return url.equals(in.url);
543 }
544
545 public void setPixelPerDegree(double ppd) {
546 this.pixelPerDegree = ppd;
547 }
548
549 /**
550 * Sets the maximum zoom level.
551 * @param defaultMaxZoom The maximum zoom level
552 */
553 public void setDefaultMaxZoom(int defaultMaxZoom) {
554 this.defaultMaxZoom = defaultMaxZoom;
555 }
556
557 /**
558 * Sets the minimum zoom level.
559 * @param defaultMinZoom The minimum zoom level
560 */
561 public void setDefaultMinZoom(int defaultMinZoom) {
562 this.defaultMinZoom = defaultMinZoom;
563 }
564
565 /**
566 * Sets the imagery polygonial bounds.
567 * @param b The imagery bounds (non-rectangular)
568 */
569 public void setBounds(ImageryBounds b) {
570 this.bounds = b;
571 }
572
573 /**
574 * Returns the imagery polygonial bounds.
575 * @return The imagery bounds (non-rectangular)
576 */
577 public ImageryBounds getBounds() {
578 return bounds;
579 }
580
581 @Override
582 public boolean requiresAttribution() {
583 return attributionText != null || attributionImage != null || termsOfUseText != null || termsOfUseURL != null;
584 }
585
586 @Override
587 public String getAttributionText(int zoom, ICoordinate topLeft, ICoordinate botRight) {
588 return attributionText;
589 }
590
591 @Override
592 public String getAttributionLinkURL() {
593 return attributionLinkURL;
594 }
595
596 @Override
597 public Image getAttributionImage() {
598 ImageIcon i = ImageProvider.getIfAvailable(attributionImage);
599 if (i != null) {
600 return i.getImage();
601 }
602 return null;
603 }
604
605 @Override
606 public String getAttributionImageURL() {
607 return attributionImageURL;
608 }
609
610 @Override
611 public String getTermsOfUseText() {
612 return termsOfUseText;
613 }
614
615 @Override
616 public String getTermsOfUseURL() {
617 return termsOfUseURL;
618 }
619
620 public void setAttributionText(String text) {
621 attributionText = text;
622 }
623
624 public void setAttributionImageURL(String text) {
625 attributionImageURL = text;
626 }
627
628 public void setAttributionImage(String text) {
629 attributionImage = text;
630 }
631
632 public void setAttributionLinkURL(String text) {
633 attributionLinkURL = text;
634 }
635
636 public void setTermsOfUseText(String text) {
637 termsOfUseText = text;
638 }
639
640 public void setTermsOfUseURL(String text) {
641 termsOfUseURL = text;
642 }
643
644 /**
645 * Sets the extended URL of this entry.
646 * @param url Entry extended URL containing in addition of service URL, its type and min/max zoom info
647 */
648 public void setExtendedUrl(String url) {
649 CheckParameterUtil.ensureParameterNotNull(url);
650
651 // Default imagery type is WMS
652 this.url = url;
653 this.imageryType = ImageryType.WMS;
654
655 defaultMaxZoom = 0;
656 defaultMinZoom = 0;
657 for (ImageryType type : ImageryType.values()) {
658 Matcher m = Pattern.compile(type.getTypeString()+"(?:\\[(?:(\\d+),)?(\\d+)\\])?:(.*)").matcher(url);
659 if (m.matches()) {
660 this.url = m.group(3);
661 this.imageryType = type;
662 if (m.group(2) != null) {
663 defaultMaxZoom = Integer.parseInt(m.group(2));
664 }
665 if (m.group(1) != null) {
666 defaultMinZoom = Integer.parseInt(m.group(1));
667 }
668 break;
669 }
670 }
671
672 if (serverProjections == null || serverProjections.isEmpty()) {
673 try {
674 serverProjections = new ArrayList<>();
675 Matcher m = Pattern.compile(".*\\{PROJ\\(([^)}]+)\\)\\}.*").matcher(url.toUpperCase(Locale.ENGLISH));
676 if (m.matches()) {
677 for (String p : m.group(1).split(",")) {
678 serverProjections.add(p);
679 }
680 }
681 } catch (Exception e) {
682 Main.warn(e);
683 }
684 }
685 }
686
687 /**
688 * Returns the entry name.
689 * @return The entry name
690 * @since 6968
691 */
692 public String getOriginalName() {
693 return this.origName != null ? this.origName : this.name;
694 }
695
696 /**
697 * Sets the entry name and handle translation.
698 * @param language The used language
699 * @param name The entry name
700 * @since 8091
701 */
702 public void setName(String language, String name) {
703 boolean isdefault = LanguageInfo.getJOSMLocaleCode(null).equals(language);
704 if (LanguageInfo.isBetterLanguage(langName, language)) {
705 this.name = isdefault ? tr(name) : name;
706 this.langName = language;
707 }
708 if (origName == null || isdefault) {
709 this.origName = name;
710 }
711 }
712
713 public void clearId() {
714 if (this.id != null) {
715 Collection<String> newAddedIds = new TreeSet<>(Main.pref.getCollection("imagery.layers.addedIds"));
716 newAddedIds.add(this.id);
717 Main.pref.putCollection("imagery.layers.addedIds", newAddedIds);
718 }
719 setId(null);
720 }
721
722 /**
723 * Determines if this entry is enabled by default.
724 * @return {@code true} if this entry is enabled by default, {@code false} otherwise
725 */
726 public boolean isDefaultEntry() {
727 return defaultEntry;
728 }
729
730 /**
731 * Sets the default state of this entry.
732 * @param defaultEntry {@code true} if this entry has to be enabled by default, {@code false} otherwise
733 */
734 public void setDefaultEntry(boolean defaultEntry) {
735 this.defaultEntry = defaultEntry;
736 }
737
738 /**
739 * Return the data part of HTTP cookies header in case the service requires cookies to work
740 * @return the cookie data part
741 */
742 @Override
743 public String getCookies() {
744 return this.cookies;
745 }
746
747 public double getPixelPerDegree() {
748 return this.pixelPerDegree;
749 }
750
751 /**
752 * Returns the maximum zoom level.
753 * @return The maximum zoom level
754 */
755 @Override
756 public int getMaxZoom() {
757 return this.defaultMaxZoom;
758 }
759
760 /**
761 * Returns the minimum zoom level.
762 * @return The minimum zoom level
763 */
764 @Override
765 public int getMinZoom() {
766 return this.defaultMinZoom;
767 }
768
769 /**
770 * Returns the description text when existing.
771 * @return The description
772 * @since 8065
773 */
774 public String getDescription() {
775 return this.description;
776 }
777
778 /**
779 * Sets the description text when existing.
780 * @param language The used language
781 * @param description the imagery description text
782 * @since 8091
783 */
784 public void setDescription(String language, String description) {
785 boolean isdefault = LanguageInfo.getJOSMLocaleCode(null).equals(language);
786 if (LanguageInfo.isBetterLanguage(langDescription, language)) {
787 this.description = isdefault ? tr(description) : description;
788 this.langDescription = language;
789 }
790 }
791
792 /**
793 * Returns a tool tip text for display.
794 * @return The text
795 * @since 8065
796 */
797 public String getToolTipText() {
798 String desc = getDescription();
799 if (desc != null && !desc.isEmpty()) {
800 return "<html>" + getName() + "<br>" + desc + "</html>";
801 }
802 return getName();
803 }
804
805 /**
806 * Returns the EULA acceptance URL, if any.
807 * @return The URL to an EULA text that has to be accepted before use, or {@code null}
808 */
809 public String getEulaAcceptanceRequired() {
810 return eulaAcceptanceRequired;
811 }
812
813 /**
814 * Sets the EULA acceptance URL.
815 * @param eulaAcceptanceRequired The URL to an EULA text that has to be accepted before use
816 */
817 public void setEulaAcceptanceRequired(String eulaAcceptanceRequired) {
818 this.eulaAcceptanceRequired = eulaAcceptanceRequired;
819 }
820
821 /**
822 * Returns the ISO 3166-1-alpha-2 country code.
823 * @return The country code (2 letters)
824 */
825 public String getCountryCode() {
826 return countryCode;
827 }
828
829 /**
830 * Sets the ISO 3166-1-alpha-2 country code.
831 * @param countryCode The country code (2 letters)
832 */
833 public void setCountryCode(String countryCode) {
834 this.countryCode = countryCode;
835 }
836
837 /**
838 * Returns the entry icon.
839 * @return The entry icon
840 */
841 public String getIcon() {
842 return icon;
843 }
844
845 /**
846 * Sets the entry icon.
847 * @param icon The entry icon
848 */
849 public void setIcon(String icon) {
850 this.icon = icon;
851 }
852
853 /**
854 * Get the projections supported by the server. Only relevant for
855 * WMS-type ImageryInfo at the moment.
856 * @return null, if no projections have been specified; the list
857 * of supported projections otherwise.
858 */
859 public List<String> getServerProjections() {
860 if (serverProjections == null)
861 return Collections.emptyList();
862 return Collections.unmodifiableList(serverProjections);
863 }
864
865 public void setServerProjections(Collection<String> serverProjections) {
866 this.serverProjections = new ArrayList<>(serverProjections);
867 }
868
869 /**
870 * Returns the extended URL, containing in addition of service URL, its type and min/max zoom info.
871 * @return The extended URL
872 */
873 public String getExtendedUrl() {
874 return imageryType.getTypeString() + (defaultMaxZoom != 0
875 ? "["+(defaultMinZoom != 0 ? Integer.toString(defaultMinZoom) + ',' : "")+defaultMaxZoom+"]" : "") + ':' + url;
876 }
877
878 public String getToolbarName() {
879 String res = name;
880 if (pixelPerDegree != 0) {
881 res += "#PPD="+pixelPerDegree;
882 }
883 return res;
884 }
885
886 public String getMenuName() {
887 String res = name;
888 if (pixelPerDegree != 0) {
889 res += " ("+pixelPerDegree+')';
890 }
891 return res;
892 }
893
894 /**
895 * Determines if this entry requires attribution.
896 * @return {@code true} if some attribution text has to be displayed, {@code false} otherwise
897 */
898 public boolean hasAttribution() {
899 return attributionText != null;
900 }
901
902 /**
903 * Copies attribution from another {@code ImageryInfo}.
904 * @param i The other imagery info to get attribution from
905 */
906 public void copyAttribution(ImageryInfo i) {
907 this.attributionImage = i.attributionImage;
908 this.attributionImageURL = i.attributionImageURL;
909 this.attributionText = i.attributionText;
910 this.attributionLinkURL = i.attributionLinkURL;
911 this.termsOfUseText = i.termsOfUseText;
912 this.termsOfUseURL = i.termsOfUseURL;
913 }
914
915 /**
916 * Applies the attribution from this object to a tile source.
917 * @param s The tile source
918 */
919 public void setAttribution(AbstractTileSource s) {
920 if (attributionText != null) {
921 if ("osm".equals(attributionText)) {
922 s.setAttributionText(new Mapnik().getAttributionText(0, null, null));
923 } else {
924 s.setAttributionText(attributionText);
925 }
926 }
927 if (attributionLinkURL != null) {
928 if ("osm".equals(attributionLinkURL)) {
929 s.setAttributionLinkURL(new Mapnik().getAttributionLinkURL());
930 } else {
931 s.setAttributionLinkURL(attributionLinkURL);
932 }
933 }
934 if (attributionImage != null) {
935 ImageIcon i = ImageProvider.getIfAvailable(null, attributionImage);
936 if (i != null) {
937 s.setAttributionImage(i.getImage());
938 }
939 }
940 if (attributionImageURL != null) {
941 s.setAttributionImageURL(attributionImageURL);
942 }
943 if (termsOfUseText != null) {
944 s.setTermsOfUseText(termsOfUseText);
945 }
946 if (termsOfUseURL != null) {
947 if ("osm".equals(termsOfUseURL)) {
948 s.setTermsOfUseURL(new Mapnik().getTermsOfUseURL());
949 } else {
950 s.setTermsOfUseURL(termsOfUseURL);
951 }
952 }
953 }
954
955 /**
956 * Returns the imagery type.
957 * @return The imagery type
958 */
959 public ImageryType getImageryType() {
960 return imageryType;
961 }
962
963 /**
964 * Sets the imagery type.
965 * @param imageryType The imagery type
966 */
967 public void setImageryType(ImageryType imageryType) {
968 this.imageryType = imageryType;
969 }
970
971 /**
972 * Returns true if this layer's URL is matched by one of the regular
973 * expressions kept by the current OsmApi instance.
974 * @return {@code true} is this entry is blacklisted, {@code false} otherwise
975 */
976 public boolean isBlacklisted() {
977 Capabilities capabilities = OsmApi.getOsmApi().getCapabilities();
978 return capabilities != null && capabilities.isOnImageryBlacklist(this.url);
979 }
980
981 /**
982 * Sets the map of &lt;header name, header value&gt; that if any of this header
983 * will be returned, then this tile will be treated as "no tile at this zoom level"
984 *
985 * @param noTileHeaders Map of &lt;header name, header value&gt; which will be treated as "no tile at this zoom level"
986 * @since 8344
987 */
988 public void setNoTileHeaders(Map<String, String> noTileHeaders) {
989 this.noTileHeaders = noTileHeaders;
990 }
991
992 @Override
993 public Map<String, String> getNoTileHeaders() {
994 return noTileHeaders;
995 }
996
997 /**
998 * Returns the map of &lt;header name, metadata key&gt; indicating, which HTTP headers should
999 * be moved to metadata
1000 *
1001 * @param metadataHeaders map of &lt;header name, metadata key&gt; indicating, which HTTP headers should be moved to metadata
1002 * @since 8418
1003 */
1004 public void setMetadataHeaders(Map<String, String> metadataHeaders) {
1005 this.metadataHeaders = metadataHeaders;
1006 }
1007
1008 public boolean isEpsg4326To3857Supported() {
1009 return isEpsg4326To3857Supported;
1010 }
1011
1012 public void setEpsg4326To3857Supported(boolean isEpsg4326To3857Supported) {
1013 this.isEpsg4326To3857Supported = isEpsg4326To3857Supported;
1014 }
1015
1016 public boolean isGeoreferenceValid() {
1017 return isGeoreferenceValid;
1018 }
1019
1020 public void setGeoreferenceValid(boolean isGeoreferenceValid) {
1021 this.isGeoreferenceValid = isGeoreferenceValid;
1022 }
1023
1024}
Note: See TracBrowser for help on using the repository browser.