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

Last change on this file since 8526 was 8526, checked in by wiktorn, 9 years ago

Introduce WMS layer based on TMS. (closes: #11255)

HEADS UP: After this patch you need to manually remove JAX-B generated file/class: org/w3/_2001/xmlschema/Adapter1.java to compile the tree again.

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