2 Copyright (C) 2001, 2006 United States Government
3 as represented by the Administrator of the
4 National Aeronautics and Space Administration.
7 package gov
.nasa
.worldwind
.util
;
9 import gov
.nasa
.worldwind
.avlist
.*;
10 import gov
.nasa
.worldwind
.geom
.*;
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
)
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
);
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
);
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)
150 return Logging
.getMessage("layers.LevelSet.InvalidLevelDescriptorFields", sb
.toString());
153 public final AVList
getParams()
158 public String
getPath()
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()
198 public final String
getDataset()
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()
238 public void setExpiryTime(long expiryTime
) // TODO: remove
240 this.expiryTime
= expiryTime
;
243 public boolean isActive()
248 public void setActive(boolean active
)
250 this.active
= active
;
253 // public interface TileURLBuilder
255 // public URL getURL(Tile tile) throws java.net.MalformedURLException;
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
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
)
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
)
314 if (o
== null || getClass() != o
.getClass())
317 final Level level
= (Level
) o
;
319 if (levelNumber
!= level
.levelNumber
)
321 if (tileHeight
!= level
.tileHeight
)
323 if (tileWidth
!= level
.tileWidth
)
325 if (cacheName
!= null ?
!cacheName
.equals(level
.cacheName
) : level
.cacheName
!= null)
327 if (dataset
!= null ?
!dataset
.equals(level
.dataset
) : level
.dataset
!= null)
329 if (formatSuffix
!= null ?
!formatSuffix
.equals(level
.formatSuffix
) : level
.formatSuffix
!= null)
331 if (levelName
!= null ?
!levelName
.equals(level
.levelName
) : level
.levelName
!= null)
333 if (service
!= null ?
!service
.equals(level
.service
) : level
.service
!= null)
335 //noinspection RedundantIfStatement
336 if (tileDelta
!= null ?
!tileDelta
.equals(level
.tileDelta
) : level
.tileDelta
!= null)
342 public int hashCode()
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);
358 public String
toString()