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
;
9 import gov
.nasa
.worldwind
.geom
.*;
15 * @version $Id: Level.java 2146 2007-06-26 07:24:14Z tgaskins $
17 public class Level
implements Comparable
<Level
>
19 private final AVList params
;
20 private final int levelNumber
;
21 private final String levelName
; // null or empty level name signifies no data resources associated with this level
22 private final LatLon tileDelta
;
23 private final int tileWidth
;
24 private final int tileHeight
;
25 private final String cacheName
;
26 private final String service
;
27 private final String dataset
;
28 private final String formatSuffix
;
29 private final double averageTexelSize
;
30 private final String path
;
31 private final TileUrlBuilder urlBuilder
;
32 private long expiryTime
= 0;
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
= WorldWind
.retrieveErrMsg("nullValue.LayerParams");
46 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, 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 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, 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
.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.
92 * @param params the list of parameters to validate.
93 * @return null if valid, otherwise a <code>String</code> containing a description of why it's invalid.
95 protected String
validate(AVList params
)
97 StringBuffer sb
= new StringBuffer();
99 Object o
= params
.getValue(AVKey
.LEVEL_NUMBER
);
100 if (o
== null || !(o
instanceof Integer
) || ((Integer
) o
) < 0)
101 sb
.append(WorldWind
.retrieveErrMsg("term.levelNumber"));
103 o
= params
.getValue(AVKey
.LEVEL_NAME
);
104 if (o
== null || !(o
instanceof String
))
105 sb
.append(WorldWind
.retrieveErrMsg("term.levelName"));
107 o
= params
.getValue(AVKey
.TILE_WIDTH
);
108 if (o
== null || !(o
instanceof Integer
) || ((Integer
) o
) < 0)
109 sb
.append(WorldWind
.retrieveErrMsg("term.tileWidth"));
111 o
= params
.getValue(AVKey
.TILE_HEIGHT
);
112 if (o
== null || !(o
instanceof Integer
) || ((Integer
) o
) < 0)
113 sb
.append(WorldWind
.retrieveErrMsg("term.tileHeight"));
115 o
= params
.getValue(AVKey
.TILE_DELTA
);
116 if (o
== null || !(o
instanceof LatLon
))
117 sb
.append(WorldWind
.retrieveErrMsg("term.tileDelta"));
119 o
= params
.getValue(AVKey
.CACHE_NAME
);
120 if (o
== null || !(o
instanceof String
) || ((String
) o
).length() < 1)
121 sb
.append(WorldWind
.retrieveErrMsg("term.cacheFolder"));
123 o
= params
.getValue(AVKey
.TILE_URL_BUILDER
);
124 if (o
== null || !(o
instanceof TileUrlBuilder
))
125 sb
.append(WorldWind
.retrieveErrMsg("term.tileURLBuilder"));
127 o
= params
.getValue(AVKey
.EXPIRY_TIME
);
128 if (o
!= null && (!(o
instanceof Long
) || ((Long
) o
) < 1))
129 sb
.append(WorldWind
.retrieveErrMsg("term.expiryTime"));
131 if (params
.getStringValue(AVKey
.LEVEL_NAME
).length() > 0)
133 o
= params
.getValue(AVKey
.SERVICE
);
134 if (o
== null || !(o
instanceof String
) || ((String
) o
).length() < 1)
135 sb
.append(WorldWind
.retrieveErrMsg("term.service"));
137 o
= params
.getValue(AVKey
.DATASET_NAME
);
138 if (o
== null || !(o
instanceof String
) || ((String
) o
).length() < 1)
139 sb
.append(WorldWind
.retrieveErrMsg("term.datasetName"));
141 o
= params
.getValue(AVKey
.FORMAT_SUFFIX
);
142 if (o
== null || !(o
instanceof String
) || ((String
) o
).length() < 1)
143 sb
.append(WorldWind
.retrieveErrMsg("term.formatSuffix"));
146 if (sb
.length() == 0)
149 return sb
.insert(0, WorldWind
.retrieveErrMsg("layers.LevelSet.InvalidLevelDescriptorFields")).toString();
152 public final AVList
getParams()
157 public String
getPath()
162 public final int getLevelNumber()
164 return this.levelNumber
;
167 public String
getLevelName()
169 return this.levelName
;
172 public LatLon
getTileDelta()
174 return this.tileDelta
;
177 public final int getTileWidth()
179 return this.tileWidth
;
182 public final int getTileHeight()
184 return this.tileHeight
;
187 public final String
getFormatSuffix()
189 return this.formatSuffix
;
192 public final String
getService()
197 public final String
getDataset()
202 public final String
getCacheName()
204 return this.cacheName
;
207 public final double getTexelSize(double radius
)
209 return radius
* this.averageTexelSize
;
212 public final boolean isEmpty()
214 return this.levelName
== null || this.levelName
.equals("");
217 public final void markResourceAbsent(long tileNumber
)
219 this.absentTiles
.markResourceAbsent(tileNumber
);
222 public final boolean isResourceAbsent(long tileNumber
)
224 return this.absentTiles
.isResourceAbsent(tileNumber
);
227 public final void unmarkResourceAbsent(long tileNumber
)
229 this.absentTiles
.unmarkResourceAbsent(tileNumber
);
232 public final long getExpiryTime()
237 public void setExpiryTime(long expiryTime
) // TODO: remove
239 this.expiryTime
= expiryTime
;
242 // public interface TileURLBuilder
244 // public URL getURL(Tile tile) throws java.net.MalformedURLException;
248 * Returns the URL necessary to retrieve the specified tile.
249 * @param tile the tile who's resources will be retrieved.
250 * @return the resource URL.
251 * @throws java.net.MalformedURLException if the URL cannot be formed from the tile's parameters.
252 * @throws IllegalArgumentException if <code>tile</code> is null.
254 public java
.net
.URL
getTileResourceURL(Tile tile
) throws java
.net
.MalformedURLException
258 String msg
= WorldWind
.retrieveErrMsg("nullValue.TileIsNull");
259 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
260 throw new IllegalArgumentException(msg
);
263 return this.urlBuilder
.getURL(tile
);
266 public int compareTo(Level that
)
270 String msg
= WorldWind
.retrieveErrMsg("nullValue.LevelIsNull");
271 WorldWind
.logger().log(java
.util
.logging
.Level
.FINE
, msg
);
272 throw new IllegalArgumentException(msg
);
274 return this.levelNumber
< that
.levelNumber ?
-1 : this.levelNumber
== that
.levelNumber ?
0 : 1;
277 public boolean equals(Object o
)
281 if (o
== null || getClass() != o
.getClass())
284 final gov
.nasa
.worldwind
.Level level
= (gov
.nasa
.worldwind
.Level
) o
;
286 if (levelNumber
!= level
.levelNumber
)
288 if (tileHeight
!= level
.tileHeight
)
290 if (tileWidth
!= level
.tileWidth
)
292 if (cacheName
!= null ?
!cacheName
.equals(level
.cacheName
) : level
.cacheName
!= null)
294 if (dataset
!= null ?
!dataset
.equals(level
.dataset
) : level
.dataset
!= null)
296 if (formatSuffix
!= null ?
!formatSuffix
.equals(level
.formatSuffix
) : level
.formatSuffix
!= null)
298 if (levelName
!= null ?
!levelName
.equals(level
.levelName
) : level
.levelName
!= null)
300 if (service
!= null ?
!service
.equals(level
.service
) : level
.service
!= null)
302 //noinspection RedundantIfStatement
303 if (tileDelta
!= null ?
!tileDelta
.equals(level
.tileDelta
) : level
.tileDelta
!= null)
309 public int hashCode()
312 result
= levelNumber
;
313 result
= 29 * result
+ (levelName
!= null ? levelName
.hashCode() : 0);
314 result
= 29 * result
+ (tileDelta
!= null ? tileDelta
.hashCode() : 0);
315 result
= 29 * result
+ tileWidth
;
316 result
= 29 * result
+ tileHeight
;
317 result
= 29 * result
+ (formatSuffix
!= null ? formatSuffix
.hashCode() : 0);
318 result
= 29 * result
+ (service
!= null ? service
.hashCode() : 0);
319 result
= 29 * result
+ (dataset
!= null ? dataset
.hashCode() : 0);
320 result
= 29 * result
+ (cacheName
!= null ? cacheName
.hashCode() : 0);
325 public String
toString()