[3719] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
[3715] | 2 | package org.openstreetmap.josm.data.imagery;
|
---|
| 3 |
|
---|
[6968] | 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
[4506] | 6 | import java.awt.Image;
|
---|
[5391] | 7 | import java.util.ArrayList;
|
---|
[4430] | 8 | import java.util.Arrays;
|
---|
[3715] | 9 | import java.util.Collection;
|
---|
[4240] | 10 | import java.util.Collections;
|
---|
| 11 | import java.util.List;
|
---|
[8404] | 12 | import java.util.Locale;
|
---|
[8344] | 13 | import java.util.Map;
|
---|
[7186] | 14 | import java.util.Objects;
|
---|
[9755] | 15 | import java.util.Set;
|
---|
[7203] | 16 | import java.util.TreeSet;
|
---|
[4188] | 17 | import java.util.regex.Matcher;
|
---|
| 18 | import java.util.regex.Pattern;
|
---|
[11216] | 19 | import java.util.stream.Collectors;
|
---|
[3715] | 20 |
|
---|
[4195] | 21 | import javax.swing.ImageIcon;
|
---|
| 22 |
|
---|
[5391] | 23 | import org.openstreetmap.gui.jmapviewer.interfaces.Attributed;
|
---|
[8526] | 24 | import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
|
---|
[5391] | 25 | import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
|
---|
| 26 | import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
|
---|
[8344] | 27 | import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo;
|
---|
[4195] | 28 | import org.openstreetmap.josm.Main;
|
---|
| 29 | import org.openstreetmap.josm.data.Bounds;
|
---|
[4450] | 30 | import org.openstreetmap.josm.data.Preferences.pref;
|
---|
[7476] | 31 | import org.openstreetmap.josm.io.Capabilities;
|
---|
[3934] | 32 | import org.openstreetmap.josm.io.OsmApi;
|
---|
[3974] | 33 | import org.openstreetmap.josm.tools.CheckParameterUtil;
|
---|
[4195] | 34 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
[8091] | 35 | import org.openstreetmap.josm.tools.LanguageInfo;
|
---|
[9755] | 36 | import org.openstreetmap.josm.tools.MultiMap;
|
---|
[11848] | 37 | import org.openstreetmap.josm.tools.Utils;
|
---|
[3934] | 38 |
|
---|
[3715] | 39 | /**
|
---|
[3826] | 40 | * Class that stores info about an image background layer.
|
---|
[3715] | 41 | *
|
---|
[6830] | 42 | * @author Frederik Ramm
|
---|
[3715] | 43 | */
|
---|
[8344] | 44 | public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInfo>, Attributed {
|
---|
[3826] | 45 |
|
---|
[6690] | 46 | /**
|
---|
| 47 | * Type of imagery entry.
|
---|
| 48 | */
|
---|
[3715] | 49 | public enum ImageryType {
|
---|
[6690] | 50 | /** A WMS (Web Map Service) entry. **/
|
---|
[3715] | 51 | WMS("wms"),
|
---|
[6690] | 52 | /** A TMS (Tile Map Service) entry. **/
|
---|
[3715] | 53 | TMS("tms"),
|
---|
[6690] | 54 | /** TMS entry for Microsoft Bing. */
|
---|
[3878] | 55 | BING("bing"),
|
---|
[6690] | 56 | /** TMS entry for Russian company <a href="https://wiki.openstreetmap.org/wiki/WikiProject_Russia/kosmosnimki">ScanEx</a>. **/
|
---|
[5617] | 57 | SCANEX("scanex"),
|
---|
[6690] | 58 | /** A WMS endpoint entry only stores the WMS server info, without layer, which are chosen later by the user. **/
|
---|
[8568] | 59 | WMS_ENDPOINT("wms_endpoint"),
|
---|
| 60 | /** WMTS stores GetCapabilities URL. Does not store any information about the layer **/
|
---|
| 61 | WMTS("wmts");
|
---|
[3715] | 62 |
|
---|
[8344] | 63 |
|
---|
[6690] | 64 | private final String typeString;
|
---|
[4861] | 65 |
|
---|
[8674] | 66 | ImageryType(String urlString) {
|
---|
[6690] | 67 | this.typeString = urlString;
|
---|
[3715] | 68 | }
|
---|
[4861] | 69 |
|
---|
[6690] | 70 | /**
|
---|
| 71 | * Returns the unique string identifying this type.
|
---|
| 72 | * @return the unique string identifying this type
|
---|
| 73 | * @since 6690
|
---|
| 74 | */
|
---|
| 75 | public final String getTypeString() {
|
---|
| 76 | return typeString;
|
---|
[3715] | 77 | }
|
---|
[6069] | 78 |
|
---|
[6690] | 79 | /**
|
---|
| 80 | * Returns the imagery type from the given type string.
|
---|
| 81 | * @param s The type string
|
---|
| 82 | * @return the imagery type matching the given type string
|
---|
| 83 | */
|
---|
| 84 | public static ImageryType fromString(String s) {
|
---|
[4861] | 85 | for (ImageryType type : ImageryType.values()) {
|
---|
[6690] | 86 | if (type.getTypeString().equals(s)) {
|
---|
[4861] | 87 | return type;
|
---|
| 88 | }
|
---|
| 89 | }
|
---|
| 90 | return null;
|
---|
| 91 | }
|
---|
[3715] | 92 | }
|
---|
[4450] | 93 |
|
---|
[6690] | 94 | /**
|
---|
| 95 | * Multi-polygon bounds for imagery backgrounds.
|
---|
| 96 | * Used to display imagery coverage in preferences and to determine relevant imagery entries based on edit location.
|
---|
| 97 | */
|
---|
[4423] | 98 | public static class ImageryBounds extends Bounds {
|
---|
[6830] | 99 |
|
---|
[6690] | 100 | /**
|
---|
| 101 | * Constructs a new {@code ImageryBounds} from string.
|
---|
| 102 | * @param asString The string containing the list of shapes defining this bounds
|
---|
| 103 | * @param separator The shape separator in the given string, usually a comma
|
---|
| 104 | */
|
---|
[4423] | 105 | public ImageryBounds(String asString, String separator) {
|
---|
| 106 | super(asString, separator);
|
---|
| 107 | }
|
---|
[3715] | 108 |
|
---|
[7005] | 109 | private List<Shape> shapes = new ArrayList<>();
|
---|
[4450] | 110 |
|
---|
[6690] | 111 | /**
|
---|
| 112 | * Adds a new shape to this bounds.
|
---|
| 113 | * @param shape The shape to add
|
---|
| 114 | */
|
---|
| 115 | public final void addShape(Shape shape) {
|
---|
[4423] | 116 | this.shapes.add(shape);
|
---|
| 117 | }
|
---|
| 118 |
|
---|
[6690] | 119 | /**
|
---|
| 120 | * Sets the list of shapes defining this bounds.
|
---|
| 121 | * @param shapes The list of shapes defining this bounds.
|
---|
| 122 | */
|
---|
| 123 | public final void setShapes(List<Shape> shapes) {
|
---|
[4423] | 124 | this.shapes = shapes;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
[6690] | 127 | /**
|
---|
| 128 | * Returns the list of shapes defining this bounds.
|
---|
| 129 | * @return The list of shapes defining this bounds
|
---|
| 130 | */
|
---|
| 131 | public final List<Shape> getShapes() {
|
---|
[4423] | 132 | return shapes;
|
---|
| 133 | }
|
---|
[6289] | 134 |
|
---|
| 135 | @Override
|
---|
| 136 | public int hashCode() {
|
---|
[9371] | 137 | return Objects.hash(super.hashCode(), shapes);
|
---|
[6289] | 138 | }
|
---|
| 139 |
|
---|
| 140 | @Override
|
---|
[9371] | 141 | public boolean equals(Object o) {
|
---|
| 142 | if (this == o) return true;
|
---|
| 143 | if (o == null || getClass() != o.getClass()) return false;
|
---|
| 144 | if (!super.equals(o)) return false;
|
---|
| 145 | ImageryBounds that = (ImageryBounds) o;
|
---|
| 146 | return Objects.equals(shapes, that.shapes);
|
---|
[6289] | 147 | }
|
---|
[4423] | 148 | }
|
---|
[7476] | 149 |
|
---|
[8091] | 150 | /** original name of the imagery entry in case of translation call, for multiple languages English when possible */
|
---|
[6968] | 151 | private String origName;
|
---|
[8091] | 152 | /** (original) language of the translated name entry */
|
---|
| 153 | private String langName;
|
---|
[8092] | 154 | /** whether this is a entry activated by default or not */
|
---|
[8840] | 155 | private boolean defaultEntry;
|
---|
[8092] | 156 | /** Whether this service requires a explicit EULA acceptance before it can be activated */
|
---|
[8840] | 157 | private String eulaAcceptanceRequired;
|
---|
[8092] | 158 | /** type of the imagery servics - WMS, TMS, ... */
|
---|
[4195] | 159 | private ImageryType imageryType = ImageryType.WMS;
|
---|
[8840] | 160 | private double pixelPerDegree;
|
---|
[8092] | 161 | /** maximum zoom level for TMS imagery */
|
---|
[8840] | 162 | private int defaultMaxZoom;
|
---|
[8092] | 163 | /** minimum zoom level for TMS imagery */
|
---|
[8840] | 164 | private int defaultMinZoom;
|
---|
[8092] | 165 | /** display bounds of imagery, displayed in prefs and used for automatic imagery selection */
|
---|
[8840] | 166 | private ImageryBounds bounds;
|
---|
[8092] | 167 | /** projections supported by WMS servers */
|
---|
[10577] | 168 | private List<String> serverProjections = Collections.emptyList();
|
---|
[8091] | 169 | /** description of the imagery entry, should contain notes what type of data it is */
|
---|
[8065] | 170 | private String description;
|
---|
[8092] | 171 | /** language of the description entry */
|
---|
[8091] | 172 | private String langDescription;
|
---|
[8092] | 173 | /** Text of a text attribution displayed when using the imagery */
|
---|
[4195] | 174 | private String attributionText;
|
---|
[11975] | 175 | /** Link to a reference stating the permission for OSM usage */
|
---|
| 176 | private String permissionReferenceURL;
|
---|
| 177 | /** Link behind the text attribution displayed when using the imagery */
|
---|
[4492] | 178 | private String attributionLinkURL;
|
---|
[8092] | 179 | /** Image of a graphical attribution displayed when using the imagery */
|
---|
[4195] | 180 | private String attributionImage;
|
---|
[8092] | 181 | /** Link behind the graphical attribution displayed when using the imagery */
|
---|
[4492] | 182 | private String attributionImageURL;
|
---|
[8092] | 183 | /** Text with usage terms displayed when using the imagery */
|
---|
[4492] | 184 | private String termsOfUseText;
|
---|
[8092] | 185 | /** Link behind the text with usage terms displayed when using the imagery */
|
---|
[4195] | 186 | private String termsOfUseURL;
|
---|
[8092] | 187 | /** country code of the imagery (for country specific imagery) */
|
---|
[4405] | 188 | private String countryCode = "";
|
---|
[11571] | 189 | /**
|
---|
[11570] | 190 | * creation date of the imagery (in the form YYYY-MM-DD;YYYY-MM-DD, where
|
---|
| 191 | * DD and MM as well as a second date are optional)
|
---|
| 192 | * @since 11570
|
---|
| 193 | */
|
---|
| 194 | private String date;
|
---|
[11575] | 195 | /**
|
---|
| 196 | * marked as best in other editors
|
---|
| 197 | * @since 11575
|
---|
| 198 | */
|
---|
[11811] | 199 | private boolean bestMarked;
|
---|
[9658] | 200 | /** mirrors of different type for this entry */
|
---|
[9978] | 201 | private List<ImageryInfo> mirrors;
|
---|
[8092] | 202 | /** icon used in menu */
|
---|
[4713] | 203 | private String icon;
|
---|
[11575] | 204 | /** is the geo reference correct - don't offer offset handling */
|
---|
[9978] | 205 | private boolean isGeoreferenceValid;
|
---|
[11216] | 206 | /** which layers should be activated by default on layer addition. **/
|
---|
[11257] | 207 | private Collection<DefaultLayer> defaultLayers = Collections.emptyList();
|
---|
[9135] | 208 | // when adding a field, also adapt the ImageryInfo(ImageryInfo)
|
---|
| 209 | // and ImageryInfo(ImageryPreferenceEntry) constructor, equals method, and ImageryPreferenceEntry
|
---|
[3715] | 210 |
|
---|
[6690] | 211 | /**
|
---|
| 212 | * Auxiliary class to save an {@link ImageryInfo} object in the preferences.
|
---|
| 213 | */
|
---|
[4450] | 214 | public static class ImageryPreferenceEntry {
|
---|
| 215 | @pref String name;
|
---|
[11570] | 216 | @pref String d;
|
---|
[7186] | 217 | @pref String id;
|
---|
[4450] | 218 | @pref String type;
|
---|
| 219 | @pref String url;
|
---|
[4452] | 220 | @pref double pixel_per_eastnorth;
|
---|
[4450] | 221 | @pref String eula;
|
---|
| 222 | @pref String attribution_text;
|
---|
| 223 | @pref String attribution_url;
|
---|
[11975] | 224 | @pref String permission_reference_url;
|
---|
[4452] | 225 | @pref String logo_image;
|
---|
[4492] | 226 | @pref String logo_url;
|
---|
| 227 | @pref String terms_of_use_text;
|
---|
[4450] | 228 | @pref String terms_of_use_url;
|
---|
| 229 | @pref String country_code = "";
|
---|
[11570] | 230 | @pref String date;
|
---|
[4450] | 231 | @pref int max_zoom;
|
---|
| 232 | @pref int min_zoom;
|
---|
| 233 | @pref String cookies;
|
---|
| 234 | @pref String bounds;
|
---|
| 235 | @pref String shapes;
|
---|
| 236 | @pref String projections;
|
---|
[4713] | 237 | @pref String icon;
|
---|
[8065] | 238 | @pref String description;
|
---|
[9755] | 239 | @pref MultiMap<String, String> noTileHeaders;
|
---|
| 240 | @pref MultiMap<String, String> noTileChecksums;
|
---|
[9619] | 241 | @pref int tileSize = -1;
|
---|
[8418] | 242 | @pref Map<String, String> metadataHeaders;
|
---|
[9134] | 243 | @pref boolean valid_georeference;
|
---|
[11575] | 244 | @pref boolean bestMarked;
|
---|
[11216] | 245 | // TODO: disabled until change of layers is implemented
|
---|
| 246 | // @pref String default_layers;
|
---|
[4450] | 247 |
|
---|
[6364] | 248 | /**
|
---|
[6690] | 249 | * Constructs a new empty WMS {@code ImageryPreferenceEntry}.
|
---|
[6364] | 250 | */
|
---|
[4450] | 251 | public ImageryPreferenceEntry() {
|
---|
[9989] | 252 | // Do nothing
|
---|
[4450] | 253 | }
|
---|
| 254 |
|
---|
[6690] | 255 | /**
|
---|
| 256 | * Constructs a new {@code ImageryPreferenceEntry} from a given {@code ImageryInfo}.
|
---|
| 257 | * @param i The corresponding imagery info
|
---|
| 258 | */
|
---|
[4450] | 259 | public ImageryPreferenceEntry(ImageryInfo i) {
|
---|
| 260 | name = i.name;
|
---|
[7186] | 261 | id = i.id;
|
---|
[6690] | 262 | type = i.imageryType.getTypeString();
|
---|
[4450] | 263 | url = i.url;
|
---|
[4452] | 264 | pixel_per_eastnorth = i.pixelPerDegree;
|
---|
[4450] | 265 | eula = i.eulaAcceptanceRequired;
|
---|
| 266 | attribution_text = i.attributionText;
|
---|
| 267 | attribution_url = i.attributionLinkURL;
|
---|
[11975] | 268 | permission_reference_url = i.permissionReferenceURL;
|
---|
[11570] | 269 | date = i.date;
|
---|
[11575] | 270 | bestMarked = i.bestMarked;
|
---|
[4452] | 271 | logo_image = i.attributionImage;
|
---|
[4492] | 272 | logo_url = i.attributionImageURL;
|
---|
| 273 | terms_of_use_text = i.termsOfUseText;
|
---|
[4450] | 274 | terms_of_use_url = i.termsOfUseURL;
|
---|
| 275 | country_code = i.countryCode;
|
---|
| 276 | max_zoom = i.defaultMaxZoom;
|
---|
| 277 | min_zoom = i.defaultMinZoom;
|
---|
| 278 | cookies = i.cookies;
|
---|
[4713] | 279 | icon = i.icon;
|
---|
[8065] | 280 | description = i.description;
|
---|
[4450] | 281 | if (i.bounds != null) {
|
---|
| 282 | bounds = i.bounds.encodeAsString(",");
|
---|
[6264] | 283 | StringBuilder shapesString = new StringBuilder();
|
---|
[4450] | 284 | for (Shape s : i.bounds.getShapes()) {
|
---|
[6264] | 285 | if (shapesString.length() > 0) {
|
---|
[8390] | 286 | shapesString.append(';');
|
---|
[4450] | 287 | }
|
---|
[6264] | 288 | shapesString.append(s.encodeAsString(","));
|
---|
[4450] | 289 | }
|
---|
[6264] | 290 | if (shapesString.length() > 0) {
|
---|
| 291 | shapes = shapesString.toString();
|
---|
[4450] | 292 | }
|
---|
| 293 | }
|
---|
[11216] | 294 | projections = i.serverProjections.stream().collect(Collectors.joining(","));
|
---|
[8344] | 295 | if (i.noTileHeaders != null && !i.noTileHeaders.isEmpty()) {
|
---|
[9755] | 296 | noTileHeaders = new MultiMap<>(i.noTileHeaders);
|
---|
[8344] | 297 | }
|
---|
[8349] | 298 |
|
---|
[9610] | 299 | if (i.noTileChecksums != null && !i.noTileChecksums.isEmpty()) {
|
---|
[9755] | 300 | noTileChecksums = new MultiMap<>(i.noTileChecksums);
|
---|
[9610] | 301 | }
|
---|
| 302 |
|
---|
[8418] | 303 | if (i.metadataHeaders != null && !i.metadataHeaders.isEmpty()) {
|
---|
| 304 | metadataHeaders = i.metadataHeaders;
|
---|
| 305 | }
|
---|
| 306 |
|
---|
[8349] | 307 | tileSize = i.getTileSize();
|
---|
[9134] | 308 |
|
---|
| 309 | valid_georeference = i.isGeoreferenceValid();
|
---|
[11216] | 310 | // TODO disabled until change of layers is implemented
|
---|
| 311 | // default_layers = i.defaultLayers.stream().collect(Collectors.joining(","));
|
---|
[4450] | 312 | }
|
---|
[6364] | 313 |
|
---|
| 314 | @Override
|
---|
| 315 | public String toString() {
|
---|
[8848] | 316 | StringBuilder s = new StringBuilder("ImageryPreferenceEntry [name=").append(name);
|
---|
[7186] | 317 | if (id != null) {
|
---|
[8848] | 318 | s.append(" id=").append(id);
|
---|
[7186] | 319 | }
|
---|
[8848] | 320 | s.append(']');
|
---|
| 321 | return s.toString();
|
---|
[6364] | 322 | }
|
---|
[4450] | 323 | }
|
---|
| 324 |
|
---|
[6364] | 325 | /**
|
---|
[6690] | 326 | * Constructs a new WMS {@code ImageryInfo}.
|
---|
[6364] | 327 | */
|
---|
[4240] | 328 | public ImageryInfo() {
|
---|
[8344] | 329 | super();
|
---|
[4240] | 330 | }
|
---|
| 331 |
|
---|
[6690] | 332 | /**
|
---|
| 333 | * Constructs a new WMS {@code ImageryInfo} with a given name.
|
---|
| 334 | * @param name The entry name
|
---|
| 335 | */
|
---|
[3715] | 336 | public ImageryInfo(String name) {
|
---|
[8344] | 337 | super(name);
|
---|
[3715] | 338 | }
|
---|
| 339 |
|
---|
[6690] | 340 | /**
|
---|
| 341 | * Constructs a new WMS {@code ImageryInfo} with given name and extended URL.
|
---|
| 342 | * @param name The entry name
|
---|
| 343 | * @param url The entry extended URL
|
---|
| 344 | */
|
---|
[3715] | 345 | public ImageryInfo(String name, String url) {
|
---|
[8344] | 346 | this(name);
|
---|
[4240] | 347 | setExtendedUrl(url);
|
---|
[3715] | 348 | }
|
---|
| 349 |
|
---|
[6690] | 350 | /**
|
---|
| 351 | * Constructs a new WMS {@code ImageryInfo} with given name, extended and EULA URLs.
|
---|
| 352 | * @param name The entry name
|
---|
| 353 | * @param url The entry URL
|
---|
| 354 | * @param eulaAcceptanceRequired The EULA URL
|
---|
| 355 | */
|
---|
[3715] | 356 | public ImageryInfo(String name, String url, String eulaAcceptanceRequired) {
|
---|
[8344] | 357 | this(name);
|
---|
[4240] | 358 | setExtendedUrl(url);
|
---|
[3715] | 359 | this.eulaAcceptanceRequired = eulaAcceptanceRequired;
|
---|
| 360 | }
|
---|
| 361 |
|
---|
[7759] | 362 | /**
|
---|
| 363 | * Constructs a new {@code ImageryInfo} with given name, url, extended and EULA URLs.
|
---|
| 364 | * @param name The entry name
|
---|
| 365 | * @param url The entry URL
|
---|
| 366 | * @param type The entry imagery type. If null, WMS will be used as default
|
---|
| 367 | * @param eulaAcceptanceRequired The EULA URL
|
---|
[8092] | 368 | * @param cookies The data part of HTTP cookies header in case the service requires cookies to work
|
---|
[7759] | 369 | * @throws IllegalArgumentException if type refers to an unknown imagery type
|
---|
| 370 | */
|
---|
[4861] | 371 | public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies) {
|
---|
[8344] | 372 | this(name);
|
---|
[4861] | 373 | setExtendedUrl(url);
|
---|
[6690] | 374 | ImageryType t = ImageryType.fromString(type);
|
---|
[8510] | 375 | this.cookies = cookies;
|
---|
[6361] | 376 | this.eulaAcceptanceRequired = eulaAcceptanceRequired;
|
---|
[4861] | 377 | if (t != null) {
|
---|
| 378 | this.imageryType = t;
|
---|
[11889] | 379 | } else if (type != null && !type.isEmpty()) {
|
---|
[7759] | 380 | throw new IllegalArgumentException("unknown type: "+type);
|
---|
[4861] | 381 | }
|
---|
| 382 | }
|
---|
| 383 |
|
---|
[11889] | 384 | /**
|
---|
| 385 | * Constructs a new {@code ImageryInfo} with given name, url, id, extended and EULA URLs.
|
---|
| 386 | * @param name The entry name
|
---|
| 387 | * @param url The entry URL
|
---|
| 388 | * @param type The entry imagery type. If null, WMS will be used as default
|
---|
| 389 | * @param eulaAcceptanceRequired The EULA URL
|
---|
| 390 | * @param cookies The data part of HTTP cookies header in case the service requires cookies to work
|
---|
| 391 | * @param id tile id
|
---|
| 392 | * @throws IllegalArgumentException if type refers to an unknown imagery type
|
---|
| 393 | */
|
---|
[8344] | 394 | public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies, String id) {
|
---|
| 395 | this(name, url, type, eulaAcceptanceRequired, cookies);
|
---|
| 396 | setId(id);
|
---|
| 397 | }
|
---|
| 398 |
|
---|
[6690] | 399 | /**
|
---|
| 400 | * Constructs a new {@code ImageryInfo} from an imagery preference entry.
|
---|
| 401 | * @param e The imagery preference entry
|
---|
| 402 | */
|
---|
[4450] | 403 | public ImageryInfo(ImageryPreferenceEntry e) {
|
---|
[8634] | 404 | super(e.name, e.url, e.id);
|
---|
[4853] | 405 | CheckParameterUtil.ensureParameterNotNull(e.name, "name");
|
---|
| 406 | CheckParameterUtil.ensureParameterNotNull(e.url, "url");
|
---|
[8065] | 407 | description = e.description;
|
---|
[4452] | 408 | cookies = e.cookies;
|
---|
[4450] | 409 | eulaAcceptanceRequired = e.eula;
|
---|
[6690] | 410 | imageryType = ImageryType.fromString(e.type);
|
---|
[4856] | 411 | if (imageryType == null) throw new IllegalArgumentException("unknown type");
|
---|
[4452] | 412 | pixelPerDegree = e.pixel_per_eastnorth;
|
---|
[4450] | 413 | defaultMaxZoom = e.max_zoom;
|
---|
| 414 | defaultMinZoom = e.min_zoom;
|
---|
| 415 | if (e.bounds != null) {
|
---|
| 416 | bounds = new ImageryBounds(e.bounds, ",");
|
---|
| 417 | if (e.shapes != null) {
|
---|
| 418 | try {
|
---|
| 419 | for (String s : e.shapes.split(";")) {
|
---|
| 420 | bounds.addShape(new Shape(s, ","));
|
---|
| 421 | }
|
---|
| 422 | } catch (IllegalArgumentException ex) {
|
---|
[6248] | 423 | Main.warn(ex);
|
---|
[4423] | 424 | }
|
---|
| 425 | }
|
---|
| 426 | }
|
---|
[11347] | 427 | if (e.projections != null && !e.projections.isEmpty()) {
|
---|
| 428 | // split generates null element on empty string which gives one element Array[null]
|
---|
[4450] | 429 | serverProjections = Arrays.asList(e.projections.split(","));
|
---|
[4430] | 430 | }
|
---|
[4450] | 431 | attributionText = e.attribution_text;
|
---|
[4492] | 432 | attributionLinkURL = e.attribution_url;
|
---|
[11975] | 433 | permissionReferenceURL = e.permission_reference_url;
|
---|
[4452] | 434 | attributionImage = e.logo_image;
|
---|
[4492] | 435 | attributionImageURL = e.logo_url;
|
---|
[11570] | 436 | date = e.date;
|
---|
[11575] | 437 | bestMarked = e.bestMarked;
|
---|
[4492] | 438 | termsOfUseText = e.terms_of_use_text;
|
---|
[4450] | 439 | termsOfUseURL = e.terms_of_use_url;
|
---|
| 440 | countryCode = e.country_code;
|
---|
[4713] | 441 | icon = e.icon;
|
---|
[8344] | 442 | if (e.noTileHeaders != null) {
|
---|
[9755] | 443 | noTileHeaders = e.noTileHeaders.toMap();
|
---|
[8344] | 444 | }
|
---|
[9610] | 445 | if (e.noTileChecksums != null) {
|
---|
[9755] | 446 | noTileChecksums = e.noTileChecksums.toMap();
|
---|
[9610] | 447 | }
|
---|
[8349] | 448 | setTileSize(e.tileSize);
|
---|
[8418] | 449 | metadataHeaders = e.metadataHeaders;
|
---|
[9134] | 450 | isGeoreferenceValid = e.valid_georeference;
|
---|
[11216] | 451 | // TODO disabled until change of layers is implemented
|
---|
| 452 | // defaultLayers = Arrays.asList(e.default_layers.split(","));
|
---|
[3715] | 453 | }
|
---|
| 454 |
|
---|
[6690] | 455 | /**
|
---|
| 456 | * Constructs a new {@code ImageryInfo} from an existing one.
|
---|
| 457 | * @param i The other imagery info
|
---|
| 458 | */
|
---|
[3715] | 459 | public ImageryInfo(ImageryInfo i) {
|
---|
[8634] | 460 | super(i.name, i.url, i.id);
|
---|
[11572] | 461 | this.origName = i.origName;
|
---|
| 462 | this.langName = i.langName;
|
---|
[11575] | 463 | this.bestMarked = i.bestMarked;
|
---|
[5369] | 464 | this.defaultEntry = i.defaultEntry;
|
---|
| 465 | this.cookies = i.cookies;
|
---|
[3715] | 466 | this.eulaAcceptanceRequired = null;
|
---|
[5369] | 467 | this.imageryType = i.imageryType;
|
---|
| 468 | this.pixelPerDegree = i.pixelPerDegree;
|
---|
| 469 | this.defaultMaxZoom = i.defaultMaxZoom;
|
---|
| 470 | this.defaultMinZoom = i.defaultMinZoom;
|
---|
[4195] | 471 | this.bounds = i.bounds;
|
---|
[5369] | 472 | this.serverProjections = i.serverProjections;
|
---|
[4492] | 473 | this.attributionText = i.attributionText;
|
---|
| 474 | this.attributionLinkURL = i.attributionLinkURL;
|
---|
[11975] | 475 | this.permissionReferenceURL = i.permissionReferenceURL;
|
---|
[4195] | 476 | this.attributionImage = i.attributionImage;
|
---|
[4492] | 477 | this.attributionImageURL = i.attributionImageURL;
|
---|
| 478 | this.termsOfUseText = i.termsOfUseText;
|
---|
[4195] | 479 | this.termsOfUseURL = i.termsOfUseURL;
|
---|
[5369] | 480 | this.countryCode = i.countryCode;
|
---|
[11570] | 481 | this.date = i.date;
|
---|
[4713] | 482 | this.icon = i.icon;
|
---|
[8065] | 483 | this.description = i.description;
|
---|
[8418] | 484 | this.noTileHeaders = i.noTileHeaders;
|
---|
[9610] | 485 | this.noTileChecksums = i.noTileChecksums;
|
---|
[8418] | 486 | this.metadataHeaders = i.metadataHeaders;
|
---|
[9134] | 487 | this.isGeoreferenceValid = i.isGeoreferenceValid;
|
---|
[11216] | 488 | this.defaultLayers = i.defaultLayers;
|
---|
[3715] | 489 | }
|
---|
| 490 |
|
---|
| 491 | @Override
|
---|
[9371] | 492 | public int hashCode() {
|
---|
| 493 | return Objects.hash(url, imageryType);
|
---|
[5369] | 494 | }
|
---|
[7476] | 495 |
|
---|
[7186] | 496 | /**
|
---|
| 497 | * Check if this object equals another ImageryInfo with respect to the properties
|
---|
| 498 | * that get written to the preference file.
|
---|
[7476] | 499 | *
|
---|
[7186] | 500 | * The field {@link #pixelPerDegree} is ignored.
|
---|
[7476] | 501 | *
|
---|
[7186] | 502 | * @param other the ImageryInfo object to compare to
|
---|
| 503 | * @return true if they are equal
|
---|
| 504 | */
|
---|
| 505 | public boolean equalsPref(ImageryInfo other) {
|
---|
| 506 | if (other == null) {
|
---|
| 507 | return false;
|
---|
| 508 | }
|
---|
[8418] | 509 |
|
---|
[11587] | 510 | // CHECKSTYLE.OFF: BooleanExpressionComplexity
|
---|
[8418] | 511 | return
|
---|
| 512 | Objects.equals(this.name, other.name) &&
|
---|
| 513 | Objects.equals(this.id, other.id) &&
|
---|
| 514 | Objects.equals(this.url, other.url) &&
|
---|
[11575] | 515 | Objects.equals(this.bestMarked, other.bestMarked) &&
|
---|
| 516 | Objects.equals(this.isGeoreferenceValid, other.isGeoreferenceValid) &&
|
---|
[8418] | 517 | Objects.equals(this.cookies, other.cookies) &&
|
---|
| 518 | Objects.equals(this.eulaAcceptanceRequired, other.eulaAcceptanceRequired) &&
|
---|
| 519 | Objects.equals(this.imageryType, other.imageryType) &&
|
---|
| 520 | Objects.equals(this.defaultMaxZoom, other.defaultMaxZoom) &&
|
---|
| 521 | Objects.equals(this.defaultMinZoom, other.defaultMinZoom) &&
|
---|
| 522 | Objects.equals(this.bounds, other.bounds) &&
|
---|
| 523 | Objects.equals(this.serverProjections, other.serverProjections) &&
|
---|
| 524 | Objects.equals(this.attributionText, other.attributionText) &&
|
---|
| 525 | Objects.equals(this.attributionLinkURL, other.attributionLinkURL) &&
|
---|
[11975] | 526 | Objects.equals(this.permissionReferenceURL, other.permissionReferenceURL) &&
|
---|
[8418] | 527 | Objects.equals(this.attributionImageURL, other.attributionImageURL) &&
|
---|
| 528 | Objects.equals(this.attributionImage, other.attributionImage) &&
|
---|
| 529 | Objects.equals(this.termsOfUseText, other.termsOfUseText) &&
|
---|
| 530 | Objects.equals(this.termsOfUseURL, other.termsOfUseURL) &&
|
---|
| 531 | Objects.equals(this.countryCode, other.countryCode) &&
|
---|
[11570] | 532 | Objects.equals(this.date, other.date) &&
|
---|
[8418] | 533 | Objects.equals(this.icon, other.icon) &&
|
---|
| 534 | Objects.equals(this.description, other.description) &&
|
---|
| 535 | Objects.equals(this.noTileHeaders, other.noTileHeaders) &&
|
---|
[9610] | 536 | Objects.equals(this.noTileChecksums, other.noTileChecksums) &&
|
---|
[11216] | 537 | Objects.equals(this.metadataHeaders, other.metadataHeaders) &&
|
---|
| 538 | Objects.equals(this.defaultLayers, other.defaultLayers);
|
---|
[11587] | 539 | // CHECKSTYLE.ON: BooleanExpressionComplexity
|
---|
[7186] | 540 | }
|
---|
[5369] | 541 |
|
---|
| 542 | @Override
|
---|
[9371] | 543 | public boolean equals(Object o) {
|
---|
| 544 | if (this == o) return true;
|
---|
| 545 | if (o == null || getClass() != o.getClass()) return false;
|
---|
| 546 | ImageryInfo that = (ImageryInfo) o;
|
---|
| 547 | return imageryType == that.imageryType && Objects.equals(url, that.url);
|
---|
[5369] | 548 | }
|
---|
| 549 |
|
---|
| 550 | @Override
|
---|
| 551 | public String toString() {
|
---|
| 552 | return "ImageryInfo{" +
|
---|
| 553 | "name='" + name + '\'' +
|
---|
| 554 | ", countryCode='" + countryCode + '\'' +
|
---|
| 555 | ", url='" + url + '\'' +
|
---|
| 556 | ", imageryType=" + imageryType +
|
---|
| 557 | '}';
|
---|
| 558 | }
|
---|
| 559 |
|
---|
| 560 | @Override
|
---|
[6690] | 561 | public int compareTo(ImageryInfo in) {
|
---|
[4405] | 562 | int i = countryCode.compareTo(in.countryCode);
|
---|
| 563 | if (i == 0) {
|
---|
[8404] | 564 | i = name.toLowerCase(Locale.ENGLISH).compareTo(in.name.toLowerCase(Locale.ENGLISH));
|
---|
[4405] | 565 | }
|
---|
| 566 | if (i == 0) {
|
---|
[3715] | 567 | i = url.compareTo(in.url);
|
---|
| 568 | }
|
---|
[4405] | 569 | if (i == 0) {
|
---|
[3715] | 570 | i = Double.compare(pixelPerDegree, in.pixelPerDegree);
|
---|
| 571 | }
|
---|
| 572 | return i;
|
---|
| 573 | }
|
---|
| 574 |
|
---|
[11889] | 575 | /**
|
---|
| 576 | * Determines if URL is equal to given imagery info.
|
---|
| 577 | * @param in imagery info
|
---|
| 578 | * @return {@code true} if URL is equal to given imagery info
|
---|
| 579 | */
|
---|
[6690] | 580 | public boolean equalsBaseValues(ImageryInfo in) {
|
---|
[3715] | 581 | return url.equals(in.url);
|
---|
| 582 | }
|
---|
| 583 |
|
---|
[10577] | 584 | /**
|
---|
| 585 | * Sets the pixel per degree value.
|
---|
| 586 | * @param ppd The ppd value
|
---|
| 587 | * @see #getPixelPerDegree()
|
---|
| 588 | */
|
---|
[3715] | 589 | public void setPixelPerDegree(double ppd) {
|
---|
| 590 | this.pixelPerDegree = ppd;
|
---|
| 591 | }
|
---|
| 592 |
|
---|
[6690] | 593 | /**
|
---|
| 594 | * Sets the maximum zoom level.
|
---|
| 595 | * @param defaultMaxZoom The maximum zoom level
|
---|
| 596 | */
|
---|
[4240] | 597 | public void setDefaultMaxZoom(int defaultMaxZoom) {
|
---|
| 598 | this.defaultMaxZoom = defaultMaxZoom;
|
---|
| 599 | }
|
---|
| 600 |
|
---|
[6690] | 601 | /**
|
---|
| 602 | * Sets the minimum zoom level.
|
---|
| 603 | * @param defaultMinZoom The minimum zoom level
|
---|
| 604 | */
|
---|
[4240] | 605 | public void setDefaultMinZoom(int defaultMinZoom) {
|
---|
| 606 | this.defaultMinZoom = defaultMinZoom;
|
---|
| 607 | }
|
---|
[4450] | 608 |
|
---|
[6690] | 609 | /**
|
---|
| 610 | * Sets the imagery polygonial bounds.
|
---|
| 611 | * @param b The imagery bounds (non-rectangular)
|
---|
| 612 | */
|
---|
[4423] | 613 | public void setBounds(ImageryBounds b) {
|
---|
[4195] | 614 | this.bounds = b;
|
---|
| 615 | }
|
---|
| 616 |
|
---|
[6690] | 617 | /**
|
---|
| 618 | * Returns the imagery polygonial bounds.
|
---|
| 619 | * @return The imagery bounds (non-rectangular)
|
---|
| 620 | */
|
---|
[4423] | 621 | public ImageryBounds getBounds() {
|
---|
[4198] | 622 | return bounds;
|
---|
| 623 | }
|
---|
| 624 |
|
---|
[4506] | 625 | @Override
|
---|
| 626 | public boolean requiresAttribution() {
|
---|
[12260] | 627 | return attributionText != null || attributionLinkURL != null || attributionImage != null
|
---|
| 628 | || termsOfUseText != null || termsOfUseURL != null;
|
---|
[4506] | 629 | }
|
---|
| 630 |
|
---|
| 631 | @Override
|
---|
[8526] | 632 | public String getAttributionText(int zoom, ICoordinate topLeft, ICoordinate botRight) {
|
---|
[4464] | 633 | return attributionText;
|
---|
| 634 | }
|
---|
| 635 |
|
---|
[4506] | 636 | @Override
|
---|
| 637 | public String getAttributionLinkURL() {
|
---|
| 638 | return attributionLinkURL;
|
---|
| 639 | }
|
---|
| 640 |
|
---|
[11975] | 641 | /**
|
---|
| 642 | * Return the permission reference URL.
|
---|
[11977] | 643 | * @return The url
|
---|
| 644 | * @see #setPermissionReferenceURL
|
---|
[11975] | 645 | * @since 11975
|
---|
| 646 | */
|
---|
| 647 | public String getPermissionReferenceURL() {
|
---|
| 648 | return permissionReferenceURL;
|
---|
| 649 | }
|
---|
| 650 |
|
---|
[4506] | 651 | @Override
|
---|
| 652 | public Image getAttributionImage() {
|
---|
| 653 | ImageIcon i = ImageProvider.getIfAvailable(attributionImage);
|
---|
| 654 | if (i != null) {
|
---|
| 655 | return i.getImage();
|
---|
| 656 | }
|
---|
| 657 | return null;
|
---|
| 658 | }
|
---|
| 659 |
|
---|
[12258] | 660 | /**
|
---|
| 661 | * Return the raw attribution logo information (an URL to the image).
|
---|
| 662 | * @return The url text
|
---|
| 663 | * @since 12257
|
---|
| 664 | */
|
---|
| 665 | public String getAttributionImageRaw() {
|
---|
| 666 | return attributionImage;
|
---|
| 667 | }
|
---|
| 668 |
|
---|
[4506] | 669 | @Override
|
---|
| 670 | public String getAttributionImageURL() {
|
---|
| 671 | return attributionImageURL;
|
---|
| 672 | }
|
---|
| 673 |
|
---|
| 674 | @Override
|
---|
| 675 | public String getTermsOfUseText() {
|
---|
| 676 | return termsOfUseText;
|
---|
| 677 | }
|
---|
| 678 |
|
---|
| 679 | @Override
|
---|
| 680 | public String getTermsOfUseURL() {
|
---|
| 681 | return termsOfUseURL;
|
---|
| 682 | }
|
---|
| 683 |
|
---|
[10577] | 684 | /**
|
---|
| 685 | * Set the attribution text
|
---|
| 686 | * @param text The text
|
---|
| 687 | * @see #getAttributionText(int, ICoordinate, ICoordinate)
|
---|
| 688 | */
|
---|
[4195] | 689 | public void setAttributionText(String text) {
|
---|
[4423] | 690 | attributionText = text;
|
---|
[4195] | 691 | }
|
---|
| 692 |
|
---|
[10577] | 693 | /**
|
---|
| 694 | * Set the attribution image
|
---|
| 695 | * @param url The url of the image.
|
---|
| 696 | * @see #getAttributionImageURL()
|
---|
| 697 | */
|
---|
| 698 | public void setAttributionImageURL(String url) {
|
---|
| 699 | attributionImageURL = url;
|
---|
[4492] | 700 | }
|
---|
| 701 |
|
---|
[10577] | 702 | /**
|
---|
| 703 | * Set the image for the attribution
|
---|
| 704 | * @param res The image resource
|
---|
| 705 | * @see #getAttributionImage()
|
---|
| 706 | */
|
---|
| 707 | public void setAttributionImage(String res) {
|
---|
| 708 | attributionImage = res;
|
---|
[4464] | 709 | }
|
---|
| 710 |
|
---|
[10577] | 711 | /**
|
---|
| 712 | * Sets the URL the attribution should link to.
|
---|
| 713 | * @param url The url.
|
---|
| 714 | * @see #getAttributionLinkURL()
|
---|
| 715 | */
|
---|
| 716 | public void setAttributionLinkURL(String url) {
|
---|
| 717 | attributionLinkURL = url;
|
---|
[4195] | 718 | }
|
---|
| 719 |
|
---|
[10577] | 720 | /**
|
---|
[11975] | 721 | * Sets the permission reference URL.
|
---|
| 722 | * @param url The url.
|
---|
| 723 | * @see #getPermissionReferenceURL()
|
---|
| 724 | * @since 11975
|
---|
| 725 | */
|
---|
| 726 | public void setPermissionReferenceURL(String url) {
|
---|
| 727 | permissionReferenceURL = url;
|
---|
| 728 | }
|
---|
| 729 |
|
---|
| 730 | /**
|
---|
[10577] | 731 | * Sets the text to display to the user as terms of use.
|
---|
| 732 | * @param text The text
|
---|
| 733 | * @see #getTermsOfUseText()
|
---|
| 734 | */
|
---|
[4492] | 735 | public void setTermsOfUseText(String text) {
|
---|
| 736 | termsOfUseText = text;
|
---|
| 737 | }
|
---|
| 738 |
|
---|
[10577] | 739 | /**
|
---|
| 740 | * Sets a url that links to the terms of use text.
|
---|
| 741 | * @param text The url.
|
---|
| 742 | * @see #getTermsOfUseURL()
|
---|
| 743 | */
|
---|
[4195] | 744 | public void setTermsOfUseURL(String text) {
|
---|
| 745 | termsOfUseURL = text;
|
---|
| 746 | }
|
---|
| 747 |
|
---|
[6690] | 748 | /**
|
---|
| 749 | * Sets the extended URL of this entry.
|
---|
| 750 | * @param url Entry extended URL containing in addition of service URL, its type and min/max zoom info
|
---|
| 751 | */
|
---|
[4240] | 752 | public void setExtendedUrl(String url) {
|
---|
[3974] | 753 | CheckParameterUtil.ensureParameterNotNull(url);
|
---|
[4450] | 754 |
|
---|
[4432] | 755 | // Default imagery type is WMS
|
---|
| 756 | this.url = url;
|
---|
| 757 | this.imageryType = ImageryType.WMS;
|
---|
| 758 |
|
---|
[4194] | 759 | defaultMaxZoom = 0;
|
---|
| 760 | defaultMinZoom = 0;
|
---|
[3715] | 761 | for (ImageryType type : ImageryType.values()) {
|
---|
[10735] | 762 | Matcher m = Pattern.compile(type.getTypeString()+"(?:\\[(?:(\\d+)[,-])?(\\d+)\\])?:(.*)").matcher(url);
|
---|
[6310] | 763 | if (m.matches()) {
|
---|
[4188] | 764 | this.url = m.group(3);
|
---|
[3715] | 765 | this.imageryType = type;
|
---|
[6310] | 766 | if (m.group(2) != null) {
|
---|
[8365] | 767 | defaultMaxZoom = Integer.parseInt(m.group(2));
|
---|
[4188] | 768 | }
|
---|
[6310] | 769 | if (m.group(1) != null) {
|
---|
[8365] | 770 | defaultMinZoom = Integer.parseInt(m.group(1));
|
---|
[4188] | 771 | }
|
---|
[4432] | 772 | break;
|
---|
[3715] | 773 | }
|
---|
| 774 | }
|
---|
| 775 |
|
---|
[10577] | 776 | if (serverProjections.isEmpty()) {
|
---|
[10212] | 777 | serverProjections = new ArrayList<>();
|
---|
| 778 | Matcher m = Pattern.compile(".*\\{PROJ\\(([^)}]+)\\)\\}.*").matcher(url.toUpperCase(Locale.ENGLISH));
|
---|
| 779 | if (m.matches()) {
|
---|
| 780 | for (String p : m.group(1).split(",")) {
|
---|
| 781 | serverProjections.add(p);
|
---|
[4432] | 782 | }
|
---|
| 783 | }
|
---|
| 784 | }
|
---|
[3715] | 785 | }
|
---|
| 786 |
|
---|
[6690] | 787 | /**
|
---|
| 788 | * Returns the entry name.
|
---|
| 789 | * @return The entry name
|
---|
[6968] | 790 | * @since 6968
|
---|
| 791 | */
|
---|
| 792 | public String getOriginalName() {
|
---|
| 793 | return this.origName != null ? this.origName : this.name;
|
---|
| 794 | }
|
---|
| 795 |
|
---|
| 796 | /**
|
---|
[8091] | 797 | * Sets the entry name and handle translation.
|
---|
[8093] | 798 | * @param language The used language
|
---|
[6968] | 799 | * @param name The entry name
|
---|
[8091] | 800 | * @since 8091
|
---|
[6968] | 801 | */
|
---|
[8091] | 802 | public void setName(String language, String name) {
|
---|
| 803 | boolean isdefault = LanguageInfo.getJOSMLocaleCode(null).equals(language);
|
---|
[8510] | 804 | if (LanguageInfo.isBetterLanguage(langName, language)) {
|
---|
[8091] | 805 | this.name = isdefault ? tr(name) : name;
|
---|
| 806 | this.langName = language;
|
---|
| 807 | }
|
---|
[8510] | 808 | if (origName == null || isdefault) {
|
---|
[8091] | 809 | this.origName = name;
|
---|
| 810 | }
|
---|
[6968] | 811 | }
|
---|
| 812 |
|
---|
[10577] | 813 | /**
|
---|
| 814 | * Store the id of this info to the preferences and clear it afterwards.
|
---|
| 815 | */
|
---|
[7203] | 816 | public void clearId() {
|
---|
| 817 | if (this.id != null) {
|
---|
| 818 | Collection<String> newAddedIds = new TreeSet<>(Main.pref.getCollection("imagery.layers.addedIds"));
|
---|
| 819 | newAddedIds.add(this.id);
|
---|
| 820 | Main.pref.putCollection("imagery.layers.addedIds", newAddedIds);
|
---|
| 821 | }
|
---|
[8634] | 822 | setId(null);
|
---|
[7203] | 823 | }
|
---|
[7186] | 824 |
|
---|
| 825 | /**
|
---|
[6690] | 826 | * Determines if this entry is enabled by default.
|
---|
| 827 | * @return {@code true} if this entry is enabled by default, {@code false} otherwise
|
---|
| 828 | */
|
---|
[4240] | 829 | public boolean isDefaultEntry() {
|
---|
| 830 | return defaultEntry;
|
---|
| 831 | }
|
---|
| 832 |
|
---|
[6690] | 833 | /**
|
---|
| 834 | * Sets the default state of this entry.
|
---|
| 835 | * @param defaultEntry {@code true} if this entry has to be enabled by default, {@code false} otherwise
|
---|
| 836 | */
|
---|
[4240] | 837 | public void setDefaultEntry(boolean defaultEntry) {
|
---|
| 838 | this.defaultEntry = defaultEntry;
|
---|
| 839 | }
|
---|
| 840 |
|
---|
[8092] | 841 | /**
|
---|
[10577] | 842 | * Gets the pixel per degree value
|
---|
| 843 | * @return The ppd value.
|
---|
| 844 | */
|
---|
[3715] | 845 | public double getPixelPerDegree() {
|
---|
| 846 | return this.pixelPerDegree;
|
---|
| 847 | }
|
---|
| 848 |
|
---|
[6690] | 849 | /**
|
---|
| 850 | * Returns the maximum zoom level.
|
---|
| 851 | * @return The maximum zoom level
|
---|
| 852 | */
|
---|
[8344] | 853 | @Override
|
---|
[3715] | 854 | public int getMaxZoom() {
|
---|
[4432] | 855 | return this.defaultMaxZoom;
|
---|
[3715] | 856 | }
|
---|
| 857 |
|
---|
[6690] | 858 | /**
|
---|
| 859 | * Returns the minimum zoom level.
|
---|
| 860 | * @return The minimum zoom level
|
---|
| 861 | */
|
---|
[8344] | 862 | @Override
|
---|
[4188] | 863 | public int getMinZoom() {
|
---|
| 864 | return this.defaultMinZoom;
|
---|
| 865 | }
|
---|
| 866 |
|
---|
[6690] | 867 | /**
|
---|
[8065] | 868 | * Returns the description text when existing.
|
---|
| 869 | * @return The description
|
---|
[8067] | 870 | * @since 8065
|
---|
[8065] | 871 | */
|
---|
| 872 | public String getDescription() {
|
---|
| 873 | return this.description;
|
---|
| 874 | }
|
---|
| 875 |
|
---|
| 876 | /**
|
---|
| 877 | * Sets the description text when existing.
|
---|
[8093] | 878 | * @param language The used language
|
---|
[8065] | 879 | * @param description the imagery description text
|
---|
[8091] | 880 | * @since 8091
|
---|
[8065] | 881 | */
|
---|
[8091] | 882 | public void setDescription(String language, String description) {
|
---|
| 883 | boolean isdefault = LanguageInfo.getJOSMLocaleCode(null).equals(language);
|
---|
[8510] | 884 | if (LanguageInfo.isBetterLanguage(langDescription, language)) {
|
---|
[8091] | 885 | this.description = isdefault ? tr(description) : description;
|
---|
| 886 | this.langDescription = language;
|
---|
| 887 | }
|
---|
[8065] | 888 | }
|
---|
| 889 |
|
---|
| 890 | /**
|
---|
| 891 | * Returns a tool tip text for display.
|
---|
| 892 | * @return The text
|
---|
[8067] | 893 | * @since 8065
|
---|
[8065] | 894 | */
|
---|
| 895 | public String getToolTipText() {
|
---|
[11649] | 896 | StringBuilder res = new StringBuilder(getName());
|
---|
[11570] | 897 | boolean html = false;
|
---|
[11649] | 898 | String dateStr = getDate();
|
---|
| 899 | if (dateStr != null && !dateStr.isEmpty()) {
|
---|
| 900 | res.append("<br>").append(tr("Date of imagery: {0}", dateStr));
|
---|
[11570] | 901 | html = true;
|
---|
| 902 | }
|
---|
[11575] | 903 | if (bestMarked) {
|
---|
[11649] | 904 | res.append("<br>").append(tr("This imagery is marked as best in this region in other editors."));
|
---|
[11619] | 905 | html = true;
|
---|
[11575] | 906 | }
|
---|
[8065] | 907 | String desc = getDescription();
|
---|
| 908 | if (desc != null && !desc.isEmpty()) {
|
---|
[11848] | 909 | res.append("<br>").append(Utils.escapeReservedCharactersHTML(desc));
|
---|
[11570] | 910 | html = true;
|
---|
[8065] | 911 | }
|
---|
[11570] | 912 | if (html) {
|
---|
[11649] | 913 | res.insert(0, "<html>").append("</html>");
|
---|
[11570] | 914 | }
|
---|
[11649] | 915 | return res.toString();
|
---|
[8065] | 916 | }
|
---|
| 917 |
|
---|
| 918 | /**
|
---|
[6690] | 919 | * Returns the EULA acceptance URL, if any.
|
---|
| 920 | * @return The URL to an EULA text that has to be accepted before use, or {@code null}
|
---|
| 921 | */
|
---|
[4195] | 922 | public String getEulaAcceptanceRequired() {
|
---|
| 923 | return eulaAcceptanceRequired;
|
---|
| 924 | }
|
---|
| 925 |
|
---|
[6690] | 926 | /**
|
---|
| 927 | * Sets the EULA acceptance URL.
|
---|
| 928 | * @param eulaAcceptanceRequired The URL to an EULA text that has to be accepted before use
|
---|
| 929 | */
|
---|
[4240] | 930 | public void setEulaAcceptanceRequired(String eulaAcceptanceRequired) {
|
---|
| 931 | this.eulaAcceptanceRequired = eulaAcceptanceRequired;
|
---|
| 932 | }
|
---|
| 933 |
|
---|
[6690] | 934 | /**
|
---|
| 935 | * Returns the ISO 3166-1-alpha-2 country code.
|
---|
| 936 | * @return The country code (2 letters)
|
---|
| 937 | */
|
---|
[4405] | 938 | public String getCountryCode() {
|
---|
| 939 | return countryCode;
|
---|
| 940 | }
|
---|
| 941 |
|
---|
[6690] | 942 | /**
|
---|
| 943 | * Sets the ISO 3166-1-alpha-2 country code.
|
---|
| 944 | * @param countryCode The country code (2 letters)
|
---|
| 945 | */
|
---|
[4405] | 946 | public void setCountryCode(String countryCode) {
|
---|
| 947 | this.countryCode = countryCode;
|
---|
| 948 | }
|
---|
| 949 |
|
---|
[6690] | 950 | /**
|
---|
[11570] | 951 | * Returns the date information.
|
---|
| 952 | * @return The date (in the form YYYY-MM-DD;YYYY-MM-DD, where
|
---|
| 953 | * DD and MM as well as a second date are optional)
|
---|
| 954 | * @since 11570
|
---|
| 955 | */
|
---|
| 956 | public String getDate() {
|
---|
| 957 | return date;
|
---|
| 958 | }
|
---|
| 959 |
|
---|
| 960 | /**
|
---|
| 961 | * Sets the date information.
|
---|
| 962 | * @param date The date information
|
---|
| 963 | * @since 11570
|
---|
| 964 | */
|
---|
| 965 | public void setDate(String date) {
|
---|
| 966 | this.date = date;
|
---|
| 967 | }
|
---|
| 968 |
|
---|
| 969 | /**
|
---|
[6690] | 970 | * Returns the entry icon.
|
---|
| 971 | * @return The entry icon
|
---|
| 972 | */
|
---|
[4713] | 973 | public String getIcon() {
|
---|
| 974 | return icon;
|
---|
| 975 | }
|
---|
| 976 |
|
---|
[6690] | 977 | /**
|
---|
| 978 | * Sets the entry icon.
|
---|
| 979 | * @param icon The entry icon
|
---|
| 980 | */
|
---|
[4713] | 981 | public void setIcon(String icon) {
|
---|
| 982 | this.icon = icon;
|
---|
| 983 | }
|
---|
| 984 |
|
---|
[4240] | 985 | /**
|
---|
| 986 | * Get the projections supported by the server. Only relevant for
|
---|
| 987 | * WMS-type ImageryInfo at the moment.
|
---|
| 988 | * @return null, if no projections have been specified; the list
|
---|
| 989 | * of supported projections otherwise.
|
---|
| 990 | */
|
---|
| 991 | public List<String> getServerProjections() {
|
---|
| 992 | return Collections.unmodifiableList(serverProjections);
|
---|
| 993 | }
|
---|
| 994 |
|
---|
[10577] | 995 | /**
|
---|
| 996 | * Sets the list of collections the server supports
|
---|
| 997 | * @param serverProjections The list of supported projections
|
---|
| 998 | */
|
---|
[4240] | 999 | public void setServerProjections(Collection<String> serverProjections) {
|
---|
[10577] | 1000 | CheckParameterUtil.ensureParameterNotNull(serverProjections, "serverProjections");
|
---|
[7005] | 1001 | this.serverProjections = new ArrayList<>(serverProjections);
|
---|
[4240] | 1002 | }
|
---|
| 1003 |
|
---|
[6690] | 1004 | /**
|
---|
| 1005 | * Returns the extended URL, containing in addition of service URL, its type and min/max zoom info.
|
---|
| 1006 | * @return The extended URL
|
---|
| 1007 | */
|
---|
[4240] | 1008 | public String getExtendedUrl() {
|
---|
[6690] | 1009 | return imageryType.getTypeString() + (defaultMaxZoom != 0
|
---|
[10462] | 1010 | ? ('['+(defaultMinZoom != 0 ? (Integer.toString(defaultMinZoom) + ',') : "")+defaultMaxZoom+']') : "") + ':' + url;
|
---|
[3715] | 1011 | }
|
---|
| 1012 |
|
---|
[10577] | 1013 | /**
|
---|
| 1014 | * Gets a unique toolbar key to store this layer as toolbar item
|
---|
| 1015 | * @return The kay.
|
---|
| 1016 | */
|
---|
[6690] | 1017 | public String getToolbarName() {
|
---|
[3715] | 1018 | String res = name;
|
---|
[8393] | 1019 | if (pixelPerDegree != 0) {
|
---|
[3715] | 1020 | res += "#PPD="+pixelPerDegree;
|
---|
| 1021 | }
|
---|
| 1022 | return res;
|
---|
| 1023 | }
|
---|
| 1024 |
|
---|
[10577] | 1025 | /**
|
---|
| 1026 | * Gets the name that should be displayed in the menu to add this imagery layer.
|
---|
| 1027 | * @return The text.
|
---|
| 1028 | */
|
---|
[6690] | 1029 | public String getMenuName() {
|
---|
[3715] | 1030 | String res = name;
|
---|
[8393] | 1031 | if (pixelPerDegree != 0) {
|
---|
[8846] | 1032 | res += " ("+pixelPerDegree+')';
|
---|
[3715] | 1033 | }
|
---|
| 1034 | return res;
|
---|
| 1035 | }
|
---|
| 1036 |
|
---|
[6690] | 1037 | /**
|
---|
| 1038 | * Determines if this entry requires attribution.
|
---|
| 1039 | * @return {@code true} if some attribution text has to be displayed, {@code false} otherwise
|
---|
| 1040 | */
|
---|
| 1041 | public boolean hasAttribution() {
|
---|
[4198] | 1042 | return attributionText != null;
|
---|
| 1043 | }
|
---|
| 1044 |
|
---|
[6690] | 1045 | /**
|
---|
| 1046 | * Copies attribution from another {@code ImageryInfo}.
|
---|
| 1047 | * @param i The other imagery info to get attribution from
|
---|
| 1048 | */
|
---|
| 1049 | public void copyAttribution(ImageryInfo i) {
|
---|
[4198] | 1050 | this.attributionImage = i.attributionImage;
|
---|
[4492] | 1051 | this.attributionImageURL = i.attributionImageURL;
|
---|
| 1052 | this.attributionText = i.attributionText;
|
---|
[4198] | 1053 | this.attributionLinkURL = i.attributionLinkURL;
|
---|
[4492] | 1054 | this.termsOfUseText = i.termsOfUseText;
|
---|
[4198] | 1055 | this.termsOfUseURL = i.termsOfUseURL;
|
---|
| 1056 | }
|
---|
| 1057 |
|
---|
[4492] | 1058 | /**
|
---|
[6690] | 1059 | * Applies the attribution from this object to a tile source.
|
---|
| 1060 | * @param s The tile source
|
---|
[4492] | 1061 | */
|
---|
[4506] | 1062 | public void setAttribution(AbstractTileSource s) {
|
---|
[4492] | 1063 | if (attributionText != null) {
|
---|
[6990] | 1064 | if ("osm".equals(attributionText)) {
|
---|
[4492] | 1065 | s.setAttributionText(new Mapnik().getAttributionText(0, null, null));
|
---|
| 1066 | } else {
|
---|
| 1067 | s.setAttributionText(attributionText);
|
---|
| 1068 | }
|
---|
| 1069 | }
|
---|
| 1070 | if (attributionLinkURL != null) {
|
---|
[6990] | 1071 | if ("osm".equals(attributionLinkURL)) {
|
---|
[4195] | 1072 | s.setAttributionLinkURL(new Mapnik().getAttributionLinkURL());
|
---|
[4492] | 1073 | } else {
|
---|
[4195] | 1074 | s.setAttributionLinkURL(attributionLinkURL);
|
---|
[4492] | 1075 | }
|
---|
[4195] | 1076 | }
|
---|
[4492] | 1077 | if (attributionImage != null) {
|
---|
[4195] | 1078 | ImageIcon i = ImageProvider.getIfAvailable(null, attributionImage);
|
---|
[4492] | 1079 | if (i != null) {
|
---|
[4195] | 1080 | s.setAttributionImage(i.getImage());
|
---|
[4492] | 1081 | }
|
---|
[4195] | 1082 | }
|
---|
[4492] | 1083 | if (attributionImageURL != null) {
|
---|
| 1084 | s.setAttributionImageURL(attributionImageURL);
|
---|
| 1085 | }
|
---|
| 1086 | if (termsOfUseText != null) {
|
---|
| 1087 | s.setTermsOfUseText(termsOfUseText);
|
---|
| 1088 | }
|
---|
| 1089 | if (termsOfUseURL != null) {
|
---|
[6990] | 1090 | if ("osm".equals(termsOfUseURL)) {
|
---|
[4195] | 1091 | s.setTermsOfUseURL(new Mapnik().getTermsOfUseURL());
|
---|
[4492] | 1092 | } else {
|
---|
[4195] | 1093 | s.setTermsOfUseURL(termsOfUseURL);
|
---|
[4492] | 1094 | }
|
---|
[4195] | 1095 | }
|
---|
| 1096 | }
|
---|
| 1097 |
|
---|
[6690] | 1098 | /**
|
---|
| 1099 | * Returns the imagery type.
|
---|
| 1100 | * @return The imagery type
|
---|
| 1101 | */
|
---|
[3715] | 1102 | public ImageryType getImageryType() {
|
---|
| 1103 | return imageryType;
|
---|
| 1104 | }
|
---|
| 1105 |
|
---|
[6690] | 1106 | /**
|
---|
| 1107 | * Sets the imagery type.
|
---|
| 1108 | * @param imageryType The imagery type
|
---|
| 1109 | */
|
---|
[4240] | 1110 | public void setImageryType(ImageryType imageryType) {
|
---|
| 1111 | this.imageryType = imageryType;
|
---|
| 1112 | }
|
---|
| 1113 |
|
---|
[3934] | 1114 | /**
|
---|
| 1115 | * Returns true if this layer's URL is matched by one of the regular
|
---|
| 1116 | * expressions kept by the current OsmApi instance.
|
---|
[6690] | 1117 | * @return {@code true} is this entry is blacklisted, {@code false} otherwise
|
---|
[3934] | 1118 | */
|
---|
[3826] | 1119 | public boolean isBlacklisted() {
|
---|
[7476] | 1120 | Capabilities capabilities = OsmApi.getOsmApi().getCapabilities();
|
---|
| 1121 | return capabilities != null && capabilities.isOnImageryBlacklist(this.url);
|
---|
[3826] | 1122 | }
|
---|
[8344] | 1123 |
|
---|
[8420] | 1124 | /**
|
---|
[8459] | 1125 | * Sets the map of <header name, header value> that if any of this header
|
---|
[8420] | 1126 | * will be returned, then this tile will be treated as "no tile at this zoom level"
|
---|
| 1127 | *
|
---|
[8459] | 1128 | * @param noTileHeaders Map of <header name, header value> which will be treated as "no tile at this zoom level"
|
---|
[9614] | 1129 | * @since 9613
|
---|
[8420] | 1130 | */
|
---|
[9755] | 1131 | public void setNoTileHeaders(MultiMap<String, String> noTileHeaders) {
|
---|
[11527] | 1132 | if (noTileHeaders == null || noTileHeaders.isEmpty()) {
|
---|
[9755] | 1133 | this.noTileHeaders = null;
|
---|
| 1134 | } else {
|
---|
| 1135 | this.noTileHeaders = noTileHeaders.toMap();
|
---|
| 1136 | }
|
---|
[8344] | 1137 | }
|
---|
| 1138 |
|
---|
| 1139 | @Override
|
---|
[9755] | 1140 | public Map<String, Set<String>> getNoTileHeaders() {
|
---|
[8344] | 1141 | return noTileHeaders;
|
---|
| 1142 | }
|
---|
[8418] | 1143 |
|
---|
[8420] | 1144 | /**
|
---|
[9610] | 1145 | * Sets the map of <checksum type, checksum value> that if any tile with that checksum
|
---|
| 1146 | * will be returned, then this tile will be treated as "no tile at this zoom level"
|
---|
| 1147 | *
|
---|
| 1148 | * @param noTileChecksums Map of <checksum type, checksum value> which will be treated as "no tile at this zoom level"
|
---|
[9614] | 1149 | * @since 9613
|
---|
[9610] | 1150 | */
|
---|
[9755] | 1151 | public void setNoTileChecksums(MultiMap<String, String> noTileChecksums) {
|
---|
[11527] | 1152 | if (noTileChecksums == null || noTileChecksums.isEmpty()) {
|
---|
[9755] | 1153 | this.noTileChecksums = null;
|
---|
| 1154 | } else {
|
---|
| 1155 | this.noTileChecksums = noTileChecksums.toMap();
|
---|
| 1156 | }
|
---|
[9610] | 1157 | }
|
---|
| 1158 |
|
---|
| 1159 | @Override
|
---|
[9755] | 1160 | public Map<String, Set<String>> getNoTileChecksums() {
|
---|
[9610] | 1161 | return noTileChecksums;
|
---|
| 1162 | }
|
---|
| 1163 |
|
---|
| 1164 | /**
|
---|
[8459] | 1165 | * Returns the map of <header name, metadata key> indicating, which HTTP headers should
|
---|
[8420] | 1166 | * be moved to metadata
|
---|
| 1167 | *
|
---|
[8459] | 1168 | * @param metadataHeaders map of <header name, metadata key> indicating, which HTTP headers should be moved to metadata
|
---|
[8420] | 1169 | * @since 8418
|
---|
| 1170 | */
|
---|
[8418] | 1171 | public void setMetadataHeaders(Map<String, String> metadataHeaders) {
|
---|
[11527] | 1172 | if (metadataHeaders == null || metadataHeaders.isEmpty()) {
|
---|
| 1173 | this.metadataHeaders = null;
|
---|
| 1174 | } else {
|
---|
| 1175 | this.metadataHeaders = metadataHeaders;
|
---|
| 1176 | }
|
---|
[8418] | 1177 | }
|
---|
[9134] | 1178 |
|
---|
[10577] | 1179 | /**
|
---|
| 1180 | * Gets the flag if the georeference is valid.
|
---|
| 1181 | * @return <code>true</code> if it is valid.
|
---|
| 1182 | */
|
---|
[9134] | 1183 | public boolean isGeoreferenceValid() {
|
---|
| 1184 | return isGeoreferenceValid;
|
---|
| 1185 | }
|
---|
| 1186 |
|
---|
[10577] | 1187 | /**
|
---|
| 1188 | * Sets an indicator that the georeference is valid
|
---|
| 1189 | * @param isGeoreferenceValid <code>true</code> if it is marked as valid.
|
---|
| 1190 | */
|
---|
[9134] | 1191 | public void setGeoreferenceValid(boolean isGeoreferenceValid) {
|
---|
| 1192 | this.isGeoreferenceValid = isGeoreferenceValid;
|
---|
| 1193 | }
|
---|
| 1194 |
|
---|
[9658] | 1195 | /**
|
---|
[11575] | 1196 | * Returns the status of "best" marked status in other editors.
|
---|
| 1197 | * @return <code>true</code> if it is marked as best.
|
---|
| 1198 | * @since 11575
|
---|
| 1199 | */
|
---|
| 1200 | public boolean isBestMarked() {
|
---|
| 1201 | return bestMarked;
|
---|
| 1202 | }
|
---|
| 1203 |
|
---|
| 1204 | /**
|
---|
| 1205 | * Sets an indicator that in other editors it is marked as best imagery
|
---|
| 1206 | * @param bestMarked <code>true</code> if it is marked as best in other editors.
|
---|
| 1207 | * @since 11575
|
---|
| 1208 | */
|
---|
| 1209 | public void setBestMarked(boolean bestMarked) {
|
---|
| 1210 | this.bestMarked = bestMarked;
|
---|
| 1211 | }
|
---|
| 1212 |
|
---|
| 1213 | /**
|
---|
[9658] | 1214 | * Adds a mirror entry. Mirror entries are completed with the data from the master entry
|
---|
| 1215 | * and only describe another method to access identical data.
|
---|
| 1216 | *
|
---|
| 1217 | * @param entry the mirror to be added
|
---|
| 1218 | * @since 9658
|
---|
| 1219 | */
|
---|
| 1220 | public void addMirror(ImageryInfo entry) {
|
---|
| 1221 | if (mirrors == null) {
|
---|
| 1222 | mirrors = new ArrayList<>();
|
---|
| 1223 | }
|
---|
| 1224 | mirrors.add(entry);
|
---|
| 1225 | }
|
---|
| 1226 |
|
---|
| 1227 | /**
|
---|
| 1228 | * Returns the mirror entries. Entries are completed with master entry data.
|
---|
| 1229 | *
|
---|
| 1230 | * @return the list of mirrors
|
---|
| 1231 | * @since 9658
|
---|
| 1232 | */
|
---|
| 1233 | public List<ImageryInfo> getMirrors() {
|
---|
| 1234 | List<ImageryInfo> l = new ArrayList<>();
|
---|
| 1235 | if (mirrors != null) {
|
---|
[11570] | 1236 | int num = 1;
|
---|
[9658] | 1237 | for (ImageryInfo i : mirrors) {
|
---|
| 1238 | ImageryInfo n = new ImageryInfo(this);
|
---|
| 1239 | if (i.defaultMaxZoom != 0) {
|
---|
| 1240 | n.defaultMaxZoom = i.defaultMaxZoom;
|
---|
| 1241 | }
|
---|
| 1242 | if (i.defaultMinZoom != 0) {
|
---|
| 1243 | n.defaultMinZoom = i.defaultMinZoom;
|
---|
| 1244 | }
|
---|
[10577] | 1245 | n.setServerProjections(i.getServerProjections());
|
---|
[9658] | 1246 | n.url = i.url;
|
---|
| 1247 | n.imageryType = i.imageryType;
|
---|
| 1248 | if (i.getTileSize() != 0) {
|
---|
| 1249 | n.setTileSize(i.getTileSize());
|
---|
| 1250 | }
|
---|
[11571] | 1251 | if (n.id != null) {
|
---|
[11570] | 1252 | n.id = n.id + "_mirror"+num;
|
---|
| 1253 | }
|
---|
[11571] | 1254 | if (num > 1) {
|
---|
[11570] | 1255 | n.name = tr("{0} mirror server {1}", n.name, num);
|
---|
[11577] | 1256 | if (n.origName != null) {
|
---|
[11572] | 1257 | n.origName += " mirror server " + num;
|
---|
| 1258 | }
|
---|
[11570] | 1259 | } else {
|
---|
| 1260 | n.name = tr("{0} mirror server", n.name);
|
---|
[11577] | 1261 | if (n.origName != null) {
|
---|
[11572] | 1262 | n.origName += " mirror server";
|
---|
| 1263 | }
|
---|
[11570] | 1264 | }
|
---|
[9658] | 1265 | l.add(n);
|
---|
[11570] | 1266 | ++num;
|
---|
[9658] | 1267 | }
|
---|
| 1268 | }
|
---|
| 1269 | return l;
|
---|
| 1270 | }
|
---|
[11216] | 1271 |
|
---|
| 1272 | /**
|
---|
| 1273 | * Returns default layers that should be shown for this Imagery (if at all supported by imagery provider)
|
---|
| 1274 | * If no layer is set to default and there is more than one imagery available, then user will be asked to choose the layer
|
---|
| 1275 | * to work on
|
---|
| 1276 | * @return Collection of the layer names
|
---|
| 1277 | */
|
---|
[11257] | 1278 | public Collection<DefaultLayer> getDefaultLayers() {
|
---|
[11216] | 1279 | return defaultLayers;
|
---|
| 1280 | }
|
---|
| 1281 |
|
---|
| 1282 | /**
|
---|
| 1283 | * Sets the default layers that user will work with
|
---|
[11217] | 1284 | * @param layers set the list of default layers
|
---|
[11216] | 1285 | */
|
---|
[11257] | 1286 | public void setDefaultLayers(Collection<DefaultLayer> layers) {
|
---|
| 1287 | if (ImageryType.WMTS.equals(this.imageryType)) {
|
---|
| 1288 | CheckParameterUtil.ensureThat(layers == null ||
|
---|
| 1289 | layers.isEmpty() ||
|
---|
| 1290 | layers.iterator().next() instanceof WMTSDefaultLayer, "Incorrect default layer");
|
---|
| 1291 | }
|
---|
[11216] | 1292 | this.defaultLayers = layers;
|
---|
| 1293 | }
|
---|
[3715] | 1294 | }
|
---|