Update to Worldwind release 0.4.1
[worldwind-tracker.git] / gov / nasa / worldwind / util / Level.java
blob276e23cffd9d95da3f6def5bbcb0a007669a272b
1 /*
2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
5 All Rights Reserved.
6 */
7 package gov.nasa.worldwind.util;
9 import gov.nasa.worldwind.avlist.*;
10 import gov.nasa.worldwind.geom.*;
12 /**
13 * @author tag
14 * @version $Id: Level.java 3575 2007-11-19 18:26:37Z tgaskins $
16 public class Level implements Comparable<Level>
18 private final AVList params;
19 private final int levelNumber;
20 private final String levelName; // null or empty level name signifies no data resources associated with this level
21 private final LatLon tileDelta;
22 private final int tileWidth;
23 private final int tileHeight;
24 private final String cacheName;
25 private final String service;
26 private final String dataset;
27 private final String formatSuffix;
28 private final double averageTexelSize;
29 private final String path;
30 private final TileUrlBuilder urlBuilder;
31 private long expiryTime = 0;
32 private boolean active = true;
34 // Absent tiles: A tile is deemed absent if a specified maximum number of attempts have been made to retrieve it.
35 // Retrieval attempts are governed by a minimum time interval between successive attempts. If an attempt is made
36 // within this interval, the tile is still deemed to be absent until the interval expires.
37 private final AbsentResourceList absentTiles;
38 int DEFAULT_MAX_ABSENT_TILE_ATTEMPTS = 2;
39 int DEFAULT_MIN_ABSENT_TILE_CHECK_INTERVAL = 10000; // milliseconds
41 public Level(AVList params)
43 if (params == null)
45 String message = Logging.getMessage("nullValue.LayerParams");
46 Logging.logger().severe(message);
47 throw new IllegalArgumentException(message);
50 this.params = params.copy(); // Private copy to insulate from subsequent changes by the app
51 String message = this.validate(params);
52 if (message != null)
54 Logging.logger().severe(message);
55 throw new IllegalArgumentException(message);
58 String ln = this.params.getStringValue(AVKey.LEVEL_NAME);
59 this.levelName = ln != null ? ln : "";
61 this.levelNumber = (Integer) this.params.getValue(AVKey.LEVEL_NUMBER);
62 this.tileDelta = (LatLon) this.params.getValue(AVKey.TILE_DELTA);
63 this.tileWidth = (Integer) this.params.getValue(AVKey.TILE_WIDTH);
64 this.tileHeight = (Integer) this.params.getValue(AVKey.TILE_HEIGHT);
65 this.cacheName = this.params.getStringValue(AVKey.DATA_CACHE_NAME);
66 this.service = this.params.getStringValue(AVKey.SERVICE);
67 this.dataset = this.params.getStringValue(AVKey.DATASET_NAME);
68 this.formatSuffix = this.params.getStringValue(AVKey.FORMAT_SUFFIX);
69 this.urlBuilder = (TileUrlBuilder) this.params.getValue(AVKey.TILE_URL_BUILDER);
70 this.expiryTime = AVListImpl.getLongValue(params, AVKey.EXPIRY_TIME, 0L);
72 double averageTileSize = 0.5 * (this.tileWidth + this.tileHeight);
73 double averageTileDelta =
74 0.5 * (this.tileDelta.getLatitude().getRadians() + this.tileDelta.getLongitude().getRadians());
75 this.averageTexelSize = averageTileDelta / averageTileSize;
77 this.path = this.cacheName + "/" + this.levelName;
79 Integer maxAbsentTileAttempts = (Integer) this.params.getValue(AVKey.MAX_ABSENT_TILE_ATTEMPTS);
80 if (maxAbsentTileAttempts == null)
81 maxAbsentTileAttempts = DEFAULT_MAX_ABSENT_TILE_ATTEMPTS;
83 Integer minAbsentTileCheckInterval = (Integer) this.params.getValue(AVKey.MIN_ABSENT_TILE_CHECK_INTERVAL);
84 if (minAbsentTileCheckInterval == null)
85 minAbsentTileCheckInterval = DEFAULT_MIN_ABSENT_TILE_CHECK_INTERVAL;
87 this.absentTiles = new AbsentResourceList(maxAbsentTileAttempts, minAbsentTileCheckInterval);
90 /**
91 * Determines whether the constructor arguments are valid.
93 * @param params the list of parameters to validate.
94 * @return null if valid, otherwise a <code>String</code> containing a description of why it's invalid.
96 protected String validate(AVList params)
98 StringBuffer sb = new StringBuffer();
100 Object o = params.getValue(AVKey.LEVEL_NUMBER);
101 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
102 sb.append(Logging.getMessage("term.levelNumber"));
104 o = params.getValue(AVKey.LEVEL_NAME);
105 if (o == null || !(o instanceof String))
106 sb.append(Logging.getMessage("term.levelName"));
108 o = params.getValue(AVKey.TILE_WIDTH);
109 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
110 sb.append(Logging.getMessage("term.tileWidth"));
112 o = params.getValue(AVKey.TILE_HEIGHT);
113 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
114 sb.append(Logging.getMessage("term.tileHeight"));
116 o = params.getValue(AVKey.TILE_DELTA);
117 if (o == null || !(o instanceof LatLon))
118 sb.append(Logging.getMessage("term.tileDelta"));
120 o = params.getValue(AVKey.DATA_CACHE_NAME);
121 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
122 sb.append(Logging.getMessage("term.cacheFolder"));
124 o = params.getValue(AVKey.TILE_URL_BUILDER);
125 if (o == null || !(o instanceof TileUrlBuilder))
126 sb.append(Logging.getMessage("term.tileURLBuilder"));
128 o = params.getValue(AVKey.EXPIRY_TIME);
129 if (o != null && (!(o instanceof Long) || ((Long) o) < 1))
130 sb.append(Logging.getMessage("term.expiryTime"));
132 if (params.getStringValue(AVKey.LEVEL_NAME).length() > 0)
134 o = params.getValue(AVKey.SERVICE);
135 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
136 sb.append(Logging.getMessage("term.service"));
138 o = params.getValue(AVKey.DATASET_NAME);
139 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
140 sb.append(Logging.getMessage("term.datasetName"));
142 o = params.getValue(AVKey.FORMAT_SUFFIX);
143 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
144 sb.append(Logging.getMessage("term.formatSuffix"));
147 if (sb.length() == 0)
148 return null;
150 return Logging.getMessage("layers.LevelSet.InvalidLevelDescriptorFields", sb.toString());
153 public final AVList getParams()
155 return params;
158 public String getPath()
160 return this.path;
163 public final int getLevelNumber()
165 return this.levelNumber;
168 public String getLevelName()
170 return this.levelName;
173 public LatLon getTileDelta()
175 return this.tileDelta;
178 public final int getTileWidth()
180 return this.tileWidth;
183 public final int getTileHeight()
185 return this.tileHeight;
188 public final String getFormatSuffix()
190 return this.formatSuffix;
193 public final String getService()
195 return this.service;
198 public final String getDataset()
200 return this.dataset;
203 public final String getCacheName()
205 return this.cacheName;
208 public final double getTexelSize(double radius)
210 return radius * this.averageTexelSize;
213 public final boolean isEmpty()
215 return this.levelName == null || this.levelName.equals("") || !this.active;
218 public final void markResourceAbsent(long tileNumber)
220 this.absentTiles.markResourceAbsent(tileNumber);
223 public final boolean isResourceAbsent(long tileNumber)
225 return this.absentTiles.isResourceAbsent(tileNumber);
228 public final void unmarkResourceAbsent(long tileNumber)
230 this.absentTiles.unmarkResourceAbsent(tileNumber);
233 public final long getExpiryTime()
235 return expiryTime;
238 public void setExpiryTime(long expiryTime) // TODO: remove
240 this.expiryTime = expiryTime;
243 public boolean isActive()
245 return this.active;
248 public void setActive(boolean active)
250 this.active = active;
253 // public interface TileURLBuilder
254 // {
255 // public URL getURL(Tile tile) throws java.net.MalformedURLException;
256 // }
259 * Returns the URL necessary to retrieve the specified tile.
261 * @param tile the tile who's resources will be retrieved.
262 * @return the resource URL.
263 * @throws java.net.MalformedURLException if the URL cannot be formed from the tile's parameters.
264 * @throws IllegalArgumentException if <code>tile</code> is null.
266 public java.net.URL getTileResourceURL(Tile tile) throws java.net.MalformedURLException
268 if (tile == null)
270 String msg = Logging.getMessage("nullValue.TileIsNull");
271 Logging.logger().severe(msg);
272 throw new IllegalArgumentException(msg);
275 return this.urlBuilder.getURL(tile);
278 public Sector computeSectorForPosition(Angle latitude, Angle longitude)
280 if (latitude == null || longitude == null)
282 String message = Logging.getMessage("nullValue.LatLonIsNull");
283 Logging.logger().severe(message);
284 throw new IllegalArgumentException(message);
287 // Compute the tile's SW lat/lon based on its row/col in the level's data set.
288 Angle dLat = this.getTileDelta().getLatitude();
289 Angle dLon = this.getTileDelta().getLongitude();
291 int row = Tile.computeRow(this.getTileDelta().getLatitude(), latitude);
292 int col = Tile.computeColumn(this.getTileDelta().getLongitude(), longitude);
293 Angle minLatitude = Tile.computeRowLatitude(row, dLat);
294 Angle minLongitude = Tile.computeColumnLongitude(col, dLon);
296 return new Sector(minLatitude, minLatitude.add(dLat), minLongitude, minLongitude.add(dLon));
299 public int compareTo(Level that)
301 if (that == null)
303 String msg = Logging.getMessage("nullValue.LevelIsNull");
304 Logging.logger().severe(msg);
305 throw new IllegalArgumentException(msg);
307 return this.levelNumber < that.levelNumber ? -1 : this.levelNumber == that.levelNumber ? 0 : 1;
310 public boolean equals(Object o)
312 if (this == o)
313 return true;
314 if (o == null || getClass() != o.getClass())
315 return false;
317 final Level level = (Level) o;
319 if (levelNumber != level.levelNumber)
320 return false;
321 if (tileHeight != level.tileHeight)
322 return false;
323 if (tileWidth != level.tileWidth)
324 return false;
325 if (cacheName != null ? !cacheName.equals(level.cacheName) : level.cacheName != null)
326 return false;
327 if (dataset != null ? !dataset.equals(level.dataset) : level.dataset != null)
328 return false;
329 if (formatSuffix != null ? !formatSuffix.equals(level.formatSuffix) : level.formatSuffix != null)
330 return false;
331 if (levelName != null ? !levelName.equals(level.levelName) : level.levelName != null)
332 return false;
333 if (service != null ? !service.equals(level.service) : level.service != null)
334 return false;
335 //noinspection RedundantIfStatement
336 if (tileDelta != null ? !tileDelta.equals(level.tileDelta) : level.tileDelta != null)
337 return false;
339 return true;
342 public int hashCode()
344 int result;
345 result = levelNumber;
346 result = 29 * result + (levelName != null ? levelName.hashCode() : 0);
347 result = 29 * result + (tileDelta != null ? tileDelta.hashCode() : 0);
348 result = 29 * result + tileWidth;
349 result = 29 * result + tileHeight;
350 result = 29 * result + (formatSuffix != null ? formatSuffix.hashCode() : 0);
351 result = 29 * result + (service != null ? service.hashCode() : 0);
352 result = 29 * result + (dataset != null ? dataset.hashCode() : 0);
353 result = 29 * result + (cacheName != null ? cacheName.hashCode() : 0);
354 return result;
357 @Override
358 public String toString()
360 return this.path;