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

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

Finish removal of tile-size workaround code started in [9617].

Now WMTS TileSources with other than 256px tile size should work properly.
See #12437, #12186

Fix name of "valid-georeference", so it will be properly loaded from preferences

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