Updated to worldwind release 20070817
[worldwind-tracker.git] / gov / nasa / worldwind / util / Level.java
blobbb5fc083572ab44899127792ca03b608ab238261
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.LatLon;
12 /**
13 * @author tag
14 * @version $Id: Level.java 2471 2007-07-31 21:50:57Z 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;
33 // Absent tiles: A tile is deemed absent if a specified maximum number of attempts have been made to retrieve it.
34 // Retrieval attempts are governed by a minimum time interval between successive attempts. If an attempt is made
35 // within this interval, the tile is still deemed to be absent until the interval expires.
36 private final AbsentResourceList absentTiles;
37 int DEFAULT_MAX_ABSENT_TILE_ATTEMPTS = 2;
38 int DEFAULT_MIN_ABSENT_TILE_CHECK_INTERVAL = 10000; // milliseconds
40 public Level(AVList params)
42 if (params == null)
44 String message = Logging.getMessage("nullValue.LayerParams");
45 Logging.logger().severe(message);
46 throw new IllegalArgumentException(message);
49 this.params = params.copy(); // Private copy to insulate from subsequent changes by the app
50 String message = this.validate(params);
51 if (message != null)
53 Logging.logger().severe(message);
54 throw new IllegalArgumentException(message);
57 String ln = this.params.getStringValue(AVKey.LEVEL_NAME);
58 this.levelName = ln != null ? ln : "";
60 this.levelNumber = (Integer) this.params.getValue(AVKey.LEVEL_NUMBER);
61 this.tileDelta = (LatLon) this.params.getValue(AVKey.TILE_DELTA);
62 this.tileWidth = (Integer) this.params.getValue(AVKey.TILE_WIDTH);
63 this.tileHeight = (Integer) this.params.getValue(AVKey.TILE_HEIGHT);
64 this.cacheName = this.params.getStringValue(AVKey.DATA_CACHE_NAME);
65 this.service = this.params.getStringValue(AVKey.SERVICE);
66 this.dataset = this.params.getStringValue(AVKey.DATASET_NAME);
67 this.formatSuffix = this.params.getStringValue(AVKey.FORMAT_SUFFIX);
68 this.urlBuilder = (TileUrlBuilder) this.params.getValue(AVKey.TILE_URL_BUILDER);
69 this.expiryTime = AVListImpl.getLongValue(params, AVKey.EXPIRY_TIME, 0L);
71 double averageTileSize = 0.5 * (this.tileWidth + this.tileHeight);
72 double averageTileDelta =
73 0.5 * (this.tileDelta.getLatitude().getRadians() + this.tileDelta.getLongitude().getRadians());
74 this.averageTexelSize = averageTileDelta / averageTileSize;
76 this.path = this.cacheName + "/" + this.levelName;
78 Integer maxAbsentTileAttempts = (Integer) this.params.getValue(AVKey.MAX_ABSENT_TILE_ATTEMPTS);
79 if (maxAbsentTileAttempts == null)
80 maxAbsentTileAttempts = DEFAULT_MAX_ABSENT_TILE_ATTEMPTS;
82 Integer minAbsentTileCheckInterval = (Integer) this.params.getValue(AVKey.MIN_ABSENT_TILE_CHECK_INTERVAL);
83 if (minAbsentTileCheckInterval == null)
84 minAbsentTileCheckInterval = DEFAULT_MIN_ABSENT_TILE_CHECK_INTERVAL;
86 this.absentTiles = new AbsentResourceList(maxAbsentTileAttempts, minAbsentTileCheckInterval);
89 /**
90 * Determines whether the constructor arguments are valid.
91 * @param params the list of parameters to validate.
92 * @return null if valid, otherwise a <code>String</code> containing a description of why it's invalid.
94 protected String validate(AVList params)
96 StringBuffer sb = new StringBuffer();
98 Object o = params.getValue(AVKey.LEVEL_NUMBER);
99 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
100 sb.append(Logging.getMessage("term.levelNumber"));
102 o = params.getValue(AVKey.LEVEL_NAME);
103 if (o == null || !(o instanceof String))
104 sb.append(Logging.getMessage("term.levelName"));
106 o = params.getValue(AVKey.TILE_WIDTH);
107 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
108 sb.append(Logging.getMessage("term.tileWidth"));
110 o = params.getValue(AVKey.TILE_HEIGHT);
111 if (o == null || !(o instanceof Integer) || ((Integer) o) < 0)
112 sb.append(Logging.getMessage("term.tileHeight"));
114 o = params.getValue(AVKey.TILE_DELTA);
115 if (o == null || !(o instanceof LatLon))
116 sb.append(Logging.getMessage("term.tileDelta"));
118 o = params.getValue(AVKey.DATA_CACHE_NAME);
119 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
120 sb.append(Logging.getMessage("term.cacheFolder"));
122 o = params.getValue(AVKey.TILE_URL_BUILDER);
123 if (o == null || !(o instanceof TileUrlBuilder))
124 sb.append(Logging.getMessage("term.tileURLBuilder"));
126 o = params.getValue(AVKey.EXPIRY_TIME);
127 if (o != null && (!(o instanceof Long) || ((Long) o) < 1))
128 sb.append(Logging.getMessage("term.expiryTime"));
130 if (params.getStringValue(AVKey.LEVEL_NAME).length() > 0)
132 o = params.getValue(AVKey.SERVICE);
133 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
134 sb.append(Logging.getMessage("term.service"));
136 o = params.getValue(AVKey.DATASET_NAME);
137 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
138 sb.append(Logging.getMessage("term.datasetName"));
140 o = params.getValue(AVKey.FORMAT_SUFFIX);
141 if (o == null || !(o instanceof String) || ((String) o).length() < 1)
142 sb.append(Logging.getMessage("term.formatSuffix"));
145 if (sb.length() == 0)
146 return null;
148 return Logging.getMessage("layers.LevelSet.InvalidLevelDescriptorFields", sb.toString());
151 public final AVList getParams()
153 return params;
156 public String getPath()
158 return this.path;
161 public final int getLevelNumber()
163 return this.levelNumber;
166 public String getLevelName()
168 return this.levelName;
171 public LatLon getTileDelta()
173 return this.tileDelta;
176 public final int getTileWidth()
178 return this.tileWidth;
181 public final int getTileHeight()
183 return this.tileHeight;
186 public final String getFormatSuffix()
188 return this.formatSuffix;
191 public final String getService()
193 return this.service;
196 public final String getDataset()
198 return this.dataset;
201 public final String getCacheName()
203 return this.cacheName;
206 public final double getTexelSize(double radius)
208 return radius * this.averageTexelSize;
211 public final boolean isEmpty()
213 return this.levelName == null || this.levelName.equals("");
216 public final void markResourceAbsent(long tileNumber)
218 this.absentTiles.markResourceAbsent(tileNumber);
221 public final boolean isResourceAbsent(long tileNumber)
223 return this.absentTiles.isResourceAbsent(tileNumber);
226 public final void unmarkResourceAbsent(long tileNumber)
228 this.absentTiles.unmarkResourceAbsent(tileNumber);
231 public final long getExpiryTime()
233 return expiryTime;
236 public void setExpiryTime(long expiryTime) // TODO: remove
238 this.expiryTime = expiryTime;
241 // public interface TileURLBuilder
242 // {
243 // public URL getURL(Tile tile) throws java.net.MalformedURLException;
244 // }
247 * Returns the URL necessary to retrieve the specified tile.
248 * @param tile the tile who's resources will be retrieved.
249 * @return the resource URL.
250 * @throws java.net.MalformedURLException if the URL cannot be formed from the tile's parameters.
251 * @throws IllegalArgumentException if <code>tile</code> is null.
253 public java.net.URL getTileResourceURL(Tile tile) throws java.net.MalformedURLException
255 if (tile == null)
257 String msg = Logging.getMessage("nullValue.TileIsNull");
258 Logging.logger().severe(msg);
259 throw new IllegalArgumentException(msg);
262 return this.urlBuilder.getURL(tile);
265 public int compareTo(Level that)
267 if (that == null)
269 String msg = Logging.getMessage("nullValue.LevelIsNull");
270 Logging.logger().severe(msg);
271 throw new IllegalArgumentException(msg);
273 return this.levelNumber < that.levelNumber ? -1 : this.levelNumber == that.levelNumber ? 0 : 1;
276 public boolean equals(Object o)
278 if (this == o)
279 return true;
280 if (o == null || getClass() != o.getClass())
281 return false;
283 final Level level = (Level) o;
285 if (levelNumber != level.levelNumber)
286 return false;
287 if (tileHeight != level.tileHeight)
288 return false;
289 if (tileWidth != level.tileWidth)
290 return false;
291 if (cacheName != null ? !cacheName.equals(level.cacheName) : level.cacheName != null)
292 return false;
293 if (dataset != null ? !dataset.equals(level.dataset) : level.dataset != null)
294 return false;
295 if (formatSuffix != null ? !formatSuffix.equals(level.formatSuffix) : level.formatSuffix != null)
296 return false;
297 if (levelName != null ? !levelName.equals(level.levelName) : level.levelName != null)
298 return false;
299 if (service != null ? !service.equals(level.service) : level.service != null)
300 return false;
301 //noinspection RedundantIfStatement
302 if (tileDelta != null ? !tileDelta.equals(level.tileDelta) : level.tileDelta != null)
303 return false;
305 return true;
308 public int hashCode()
310 int result;
311 result = levelNumber;
312 result = 29 * result + (levelName != null ? levelName.hashCode() : 0);
313 result = 29 * result + (tileDelta != null ? tileDelta.hashCode() : 0);
314 result = 29 * result + tileWidth;
315 result = 29 * result + tileHeight;
316 result = 29 * result + (formatSuffix != null ? formatSuffix.hashCode() : 0);
317 result = 29 * result + (service != null ? service.hashCode() : 0);
318 result = 29 * result + (dataset != null ? dataset.hashCode() : 0);
319 result = 29 * result + (cacheName != null ? cacheName.hashCode() : 0);
320 return result;
323 @Override
324 public String toString()
326 return this.path;