Update to Worldwind release 20070920
[worldwind-tracker.git] / gov / nasa / worldwind / layers / placename / PlaceNameLayer.java
blobd963d1633dbd95ad98c72c4af9ad77e5b630b10b
1 /*
2 Copyright (C) 2001, 2006 United States Government as represented by
3 the Administrator of the National Aeronautics and Space Administration.
4 All Rights Reserved.
5 */
6 package gov.nasa.worldwind.layers.placename;
8 import com.sun.opengl.util.BufferUtil;
9 import gov.nasa.worldwind.*;
10 import gov.nasa.worldwind.avlist.AVKey;
11 import gov.nasa.worldwind.cache.*;
12 import gov.nasa.worldwind.geom.*;
13 import gov.nasa.worldwind.layers.AbstractLayer;
14 import gov.nasa.worldwind.pick.PlaceName;
15 import gov.nasa.worldwind.render.*;
16 import gov.nasa.worldwind.retrieve.*;
17 import gov.nasa.worldwind.util.*;
18 import gov.nasa.worldwind.view.View;
20 import java.awt.*;
21 import java.util.*;
22 import java.util.List;
23 import java.util.Queue;
24 import java.util.concurrent.LinkedBlockingQueue;
25 import java.util.logging.Level;
27 /**
28 * @author Paul Collins
29 * @version $Id: PlaceNameLayer.java 2980 2007-09-22 01:07:06Z tgaskins $
31 public class PlaceNameLayer extends AbstractLayer
33 private final PlaceNameServiceSet placeNameServiceSet;
34 private final List<Tile[]> tiles = new ArrayList<Tile[]>();
35 private final MemoryCache memoryCache;
37 /**
38 * @param placeNameServiceSet the set of PlaceNameService objects that PlaceNameLayer will render.
39 * @throws IllegalArgumentException if <code>placeNameServiceSet</code> is null
41 public PlaceNameLayer(PlaceNameServiceSet placeNameServiceSet)
43 if (placeNameServiceSet == null)
45 String message = Logging.getMessage("nullValue.PlaceNameServiceSetIsNull");
46 Logging.logger().fine(message);
47 throw new IllegalArgumentException(message);
50 String cacheName = Tile.class.getName();
51 if (WorldWind.getMemoryCacheSet().containsCache(cacheName))
53 this.memoryCache = WorldWind.getMemoryCache(cacheName);
55 else
57 long size = Configuration.getLongValue(AVKey.PLACENAME_LAYER_CACHE_SIZE, 2000000L);
58 this.memoryCache = new BasicMemoryCache((long) (0.85 * size), size);
59 this.memoryCache.setName("Placenames");
60 WorldWind.getMemoryCacheSet().addCache(cacheName, this.memoryCache);
63 this.placeNameServiceSet = placeNameServiceSet.deepCopy();
64 for (int i = 0; i < this.placeNameServiceSet.getServiceCount(); i++)
66 tiles.add(i, buildTiles(this.placeNameServiceSet.getService(i)));
70 public final PlaceNameServiceSet getPlaceNameServiceSet()
72 return this.placeNameServiceSet;
75 // ============== Tile Assembly ======================= //
76 // ============== Tile Assembly ======================= //
77 // ============== Tile Assembly ======================= //
79 private static class Tile
81 final PlaceNameService placeNameService;
82 final Sector sector;
83 final int row;
84 final int column;
85 final int hash;
86 // Computed data.
87 String fileCachePath = null;
88 Extent extent = null;
89 double extentVerticalExaggeration = Double.MIN_VALUE;
91 static int computeRow(Angle delta, Angle latitude)
93 if (delta == null || latitude == null)
95 String msg = Logging.getMessage("nullValue.AngleIsNull");
96 Logging.logger().severe(msg);
97 throw new IllegalArgumentException(msg);
99 return (int) ((latitude.getDegrees() + 90d) / delta.getDegrees());
102 static int computeColumn(Angle delta, Angle longitude)
104 if (delta == null || longitude == null)
106 String msg = Logging.getMessage("nullValue.AngleIsNull");
107 Logging.logger().severe(msg);
108 throw new IllegalArgumentException(msg);
110 return (int) ((longitude.getDegrees() + 180d) / delta.getDegrees());
113 static Angle computeRowLatitude(int row, Angle delta)
115 if (delta == null)
117 String msg = Logging.getMessage("nullValue.AngleIsNull");
118 Logging.logger().severe(msg);
119 throw new IllegalArgumentException(msg);
121 return Angle.fromDegrees(-90d + delta.getDegrees() * row);
124 static Angle computeColumnLongitude(int column, Angle delta)
126 if (delta == null)
128 String msg = Logging.getMessage("nullValue.AngleIsNull");
129 Logging.logger().severe(msg);
130 throw new IllegalArgumentException(msg);
132 return Angle.fromDegrees(-180 + delta.getDegrees() * column);
135 Tile(PlaceNameService placeNameService, Sector sector, int row, int column)
137 this.placeNameService = placeNameService;
138 this.sector = sector;
139 this.row = row;
140 this.column = column;
141 this.hash = this.computeHash();
144 int computeHash()
146 return this.getFileCachePath() != null ? this.getFileCachePath().hashCode() : 0;
149 @Override
150 public boolean equals(Object o)
152 if (this == o)
153 return true;
154 if (o == null || this.getClass() != o.getClass())
155 return false;
157 final Tile other = (Tile) o;
159 return this.getFileCachePath() != null ? !this.getFileCachePath().equals(other.getFileCachePath()) :
160 other.getFileCachePath() != null;
163 Extent getExtent(DrawContext dc)
165 if (dc == null)
167 String message = Logging.getMessage("nullValue.DrawContextIsNull");
168 Logging.logger().fine(message);
169 throw new IllegalArgumentException(message);
172 if (this.extent == null || this.extentVerticalExaggeration != dc.getVerticalExaggeration())
174 this.extentVerticalExaggeration = dc.getVerticalExaggeration();
175 this.extent = Sector.computeBoundingCylinder(dc.getGlobe(), this.extentVerticalExaggeration,
176 this.sector);
179 return extent;
182 String getFileCachePath()
184 if (this.fileCachePath == null)
185 this.fileCachePath = this.placeNameService.createFileCachePathFromTile(this.row, this.column);
187 return this.fileCachePath;
190 PlaceNameService getPlaceNameService()
192 return placeNameService;
195 java.net.URL getRequestURL() throws java.net.MalformedURLException
197 return this.placeNameService.createServiceURLFromSector(this.sector);
200 Sector getSector()
202 return sector;
205 public int hashCode()
207 return this.hash;
211 private Tile[] buildTiles(PlaceNameService placeNameService)
213 final Sector sector = placeNameService.getSector();
214 final Angle dLat = placeNameService.getTileDelta().getLatitude();
215 final Angle dLon = placeNameService.getTileDelta().getLongitude();
217 // Determine the row and column offset from the global tiling origin for the southwest tile corner
218 int firstRow = Tile.computeRow(dLat, sector.getMinLatitude());
219 int firstCol = Tile.computeColumn(dLon, sector.getMinLongitude());
220 int lastRow = Tile.computeRow(dLat, sector.getMaxLatitude().subtract(dLat));
221 int lastCol = Tile.computeColumn(dLon, sector.getMaxLongitude().subtract(dLon));
223 int nLatTiles = lastRow - firstRow + 1;
224 int nLonTiles = lastCol - firstCol + 1;
226 Tile[] tiles = new Tile[nLatTiles * nLonTiles];
228 Angle p1 = Tile.computeRowLatitude(firstRow, dLat);
229 for (int row = firstRow; row <= lastRow; row++)
231 Angle p2;
232 p2 = p1.add(dLat);
234 Angle t1 = Tile.computeColumnLongitude(firstCol, dLon);
235 for (int col = firstCol; col <= lastCol; col++)
237 Angle t2;
238 t2 = t1.add(dLon);
240 tiles[col + row * nLonTiles] = new Tile(placeNameService, new Sector(p1, p2, t1, t2), row, col);
241 t1 = t2;
243 p1 = p2;
246 return tiles;
249 // ============== Place Name Data Structures ======================= //
250 // ============== Place Name Data Structures ======================= //
251 // ============== Place Name Data Structures ======================= //
253 private static class PlaceNameChunk implements Cacheable
255 final PlaceNameService placeNameService;
256 final StringBuilder textArray;
257 final int[] textIndexArray;
258 final double[] latlonArray;
259 final int numEntries;
260 final long estimatedMemorySize;
262 PlaceNameChunk(PlaceNameService service, StringBuilder text, int[] textIndices,
263 double[] positions, int numEntries)
265 this.placeNameService = service;
266 this.textArray = text;
267 this.textIndexArray = textIndices;
268 this.latlonArray = positions;
269 this.numEntries = numEntries;
270 this.estimatedMemorySize = this.computeEstimatedMemorySize();
273 long computeEstimatedMemorySize()
275 long result = 0;
276 result += BufferUtil.SIZEOF_SHORT * textArray.capacity();
277 result += BufferUtil.SIZEOF_INT * textIndexArray.length;
278 result += BufferUtil.SIZEOF_DOUBLE * latlonArray.length;
279 return result;
282 Position getPosition(int index)
284 int latlonIndex = 2 * index;
285 return Position.fromDegrees(latlonArray[latlonIndex], latlonArray[latlonIndex + 1], 0);
288 PlaceNameService getPlaceNameService()
290 return this.placeNameService;
293 String getText(int index)
295 int beginIndex = textIndexArray[index];
296 int endIndex = (index + 1 < numEntries) ? textIndexArray[index + 1] : textArray.length();
297 return this.textArray.substring(beginIndex, endIndex);
300 public long getSizeInBytes()
302 return this.estimatedMemorySize;
305 Iterator<PlaceName> createRenderIterator(final DrawContext dc)
307 return new Iterator<PlaceName>()
309 PlaceNameImpl placeNameProxy = new PlaceNameImpl();
310 int index = -1;
312 public boolean hasNext()
314 return index < (PlaceNameChunk.this.numEntries - 1);
317 public PlaceName next()
319 if (!hasNext())
320 throw new NoSuchElementException();
321 this.updateProxy(placeNameProxy, ++index);
322 return placeNameProxy;
325 public void remove()
327 throw new UnsupportedOperationException();
330 void updateProxy(PlaceNameImpl proxy, int index)
332 proxy.text = getText(index);
333 proxy.position = getPosition(index);
334 proxy.font = placeNameService.getFont();
335 proxy.color = placeNameService.getColor();
336 proxy.visible = isNameVisible(dc, placeNameService, proxy.position);
342 private static class PlaceNameImpl implements PlaceName
344 String text;
345 Position position;
346 Font font;
347 Color color;
348 boolean visible;
350 PlaceNameImpl()
354 public String getText()
356 return this.text;
359 public void setText(String text)
361 throw new UnsupportedOperationException();
364 public Position getPosition()
366 return this.position;
369 public void setPosition(Position position)
371 throw new UnsupportedOperationException();
374 public Font getFont()
376 return this.font;
379 public void setFont(Font font)
381 throw new UnsupportedOperationException();
384 public Color getColor()
386 return this.color;
389 public void setColor(Color color)
391 throw new UnsupportedOperationException();
394 public boolean isVisible()
396 return this.visible;
399 public void setVisible(boolean visible)
401 throw new UnsupportedOperationException();
404 public WWIcon getIcon()
406 return null;
409 public void setIcon(WWIcon icon)
411 throw new UnsupportedOperationException();
415 // ============== Rendering ======================= //
416 // ============== Rendering ======================= //
417 // ============== Rendering ======================= //
419 private final PlaceNameRenderer placeNameRenderer = new PlaceNameRenderer();
421 @Override
422 public void dispose() // override if disposal is a supported operation
424 super.dispose();
426 if (this.placeNameRenderer != null)
427 this.placeNameRenderer.dispose();
430 @Override
431 protected void doRender(DrawContext dc)
433 boolean enableDepthTest = this.isEnableDepthTest(dc);
435 int serviceCount = this.placeNameServiceSet.getServiceCount();
436 for (int i = 0; i < serviceCount; i++)
438 PlaceNameService placeNameService = this.placeNameServiceSet.getService(i);
439 if (!isServiceVisible(dc, placeNameService))
440 continue;
442 double minDist = placeNameService.getMinDisplayDistance();
443 double maxDist = placeNameService.getMaxDisplayDistance();
444 double minDistSquared = minDist * minDist;
445 double maxDistSquared = maxDist * maxDist;
447 Tile[] tiles = this.tiles.get(i);
448 for (Tile tile : tiles)
452 drawOrRequestTile(dc, tile, minDistSquared, maxDistSquared, enableDepthTest);
454 catch (Exception e)
456 Logging.logger().log(Level.FINE, Logging.getMessage("layers.PlaceNameLayer.ExceptionRenderingTile"),
462 this.sendRequests();
465 private boolean isEnableDepthTest(DrawContext dc)
467 Position eyePos = dc.getView().getEyePosition();
468 if (eyePos == null)
469 return false;
471 double altitude = eyePos.getElevation();
472 return altitude < (dc.getVerticalExaggeration() * dc.getGlobe().getMaxElevation());
475 private void drawOrRequestTile(DrawContext dc, Tile tile, double minDisplayDistanceSquared,
476 double maxDisplayDistanceSquared, boolean enableDepthTest)
478 if (!isTileVisible(dc, tile, minDisplayDistanceSquared, maxDisplayDistanceSquared))
479 return;
481 Object cacheObj = this.memoryCache.getObject(tile);
482 if (cacheObj == null)
484 this.requestTile(this.readQueue, tile);
485 return;
488 if (!(cacheObj instanceof PlaceNameChunk))
489 return;
491 PlaceNameChunk placeNameChunk = (PlaceNameChunk) cacheObj;
492 Iterator<PlaceName> renderIter = placeNameChunk.createRenderIterator(dc);
493 placeNameRenderer.render(dc, renderIter, enableDepthTest);
496 private static boolean isServiceVisible(DrawContext dc, PlaceNameService placeNameService)
498 if (!placeNameService.isEnabled())
499 return false;
500 //noinspection SimplifiableIfStatement
501 if (dc.getVisibleSector() != null && !placeNameService.getSector().intersects(dc.getVisibleSector()))
502 return false;
504 return placeNameService.getExtent(dc).intersects(dc.getView().getFrustumInModelCoordinates());
507 private static boolean isTileVisible(DrawContext dc, Tile tile, double minDistanceSquared,
508 double maxDistanceSquared)
510 if (!tile.getSector().intersects(dc.getVisibleSector()))
511 return false;
513 View view = dc.getView();
514 Position eyePos = view.getEyePosition();
515 if (eyePos == null)
516 return false;
518 Angle lat = clampAngle(eyePos.getLatitude(), tile.getSector().getMinLatitude(),
519 tile.getSector().getMaxLatitude());
520 Angle lon = clampAngle(eyePos.getLongitude(), tile.getSector().getMinLongitude(),
521 tile.getSector().getMaxLongitude());
522 Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
523 double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
524 //noinspection RedundantIfStatement
525 if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared)
526 return false;
528 return true;
531 private static boolean isNameVisible(DrawContext dc, PlaceNameService service, Position namePosition)
533 double elevation = dc.getVerticalExaggeration() * namePosition.getElevation();
534 Vec4 namePoint = dc.getGlobe().computePointFromPosition(namePosition.getLatitude(),
535 namePosition.getLongitude(), elevation);
536 Vec4 eyeVec = dc.getView().getEyePoint();
538 double dist = eyeVec.distanceTo3(namePoint);
539 return dist >= service.getMinDisplayDistance() && dist <= service.getMaxDisplayDistance();
542 private static Angle clampAngle(Angle a, Angle min, Angle max)
544 return a.compareTo(min) < 0 ? min : (a.compareTo(max) > 0 ? max : a);
547 // ============== Image Reading and Downloading ======================= //
548 // ============== Image Reading and Downloading ======================= //
549 // ============== Image Reading and Downloading ======================= //
551 private static final int MAX_REQUESTS = 64;
552 private final Queue<Tile> downloadQueue = new LinkedBlockingQueue<Tile>(MAX_REQUESTS);
553 private final Queue<Tile> readQueue = new LinkedBlockingQueue<Tile>(MAX_REQUESTS);
555 private static class RequestTask implements Runnable
557 final PlaceNameLayer layer;
558 final Tile tile;
560 RequestTask(PlaceNameLayer layer, Tile tile)
562 this.layer = layer;
563 this.tile = tile;
566 @Override
567 public boolean equals(Object o)
569 if (this == o)
570 return true;
571 if (o == null || this.getClass() != o.getClass())
572 return false;
574 final RequestTask other = (RequestTask) o;
576 // Don't include layer in comparison so that requests are shared among layers
577 return !(this.tile != null ? !this.tile.equals(other.tile) : other.tile != null);
580 @Override
581 public int hashCode()
583 return (this.tile != null ? this.tile.hashCode() : 0);
586 public void run()
588 synchronized (tile)
590 if (this.layer.memoryCache.getObject(this.tile) != null)
591 return;
593 final java.net.URL tileURL = WorldWind.getDataFileCache().findFile(tile.getFileCachePath(), false);
594 if (tileURL != null)
596 if (this.layer.loadTile(this.tile, tileURL))
598 tile.getPlaceNameService().unmarkResourceAbsent(tile.getPlaceNameService().getTileNumber(
599 tile.row,
600 tile.column));
601 this.layer.firePropertyChange(AVKey.LAYER, null, this);
603 else
605 // Assume that something's wrong with the file and delete it.
606 WorldWind.getDataFileCache().removeFile(tileURL);
607 tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
608 tile.column));
609 String message = Logging.getMessage("generic.DeletedCorruptDataFile", tileURL);
610 Logging.logger().fine(message);
612 return;
616 this.layer.requestTile(this.layer.downloadQueue, this.tile);
619 public String toString()
621 return this.tile.toString();
625 private static class DownloadPostProcessor implements RetrievalPostProcessor
627 final PlaceNameLayer layer;
628 final Tile tile;
630 private DownloadPostProcessor(PlaceNameLayer layer, Tile tile)
632 this.layer = layer;
633 this.tile = tile;
636 public java.nio.ByteBuffer run(Retriever retriever)
638 if (retriever == null)
640 String msg = Logging.getMessage("nullValue.RetrieverIsNull");
641 Logging.logger().fine(msg);
642 throw new IllegalArgumentException(msg);
645 if (!retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL))
646 return null;
648 if (!(retriever instanceof URLRetriever))
649 return null;
653 if (retriever instanceof HTTPRetriever)
655 HTTPRetriever httpRetriever = (HTTPRetriever) retriever;
656 if (httpRetriever.getResponseCode() == java.net.HttpURLConnection.HTTP_NO_CONTENT)
658 // Mark tile as missing to avoid further attempts
659 tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
660 tile.column));
661 return null;
665 URLRetriever urlRetriever = (URLRetriever) retriever;
666 java.nio.ByteBuffer buffer = urlRetriever.getBuffer();
668 synchronized (tile)
670 final java.io.File cacheFile = WorldWind.getDataFileCache().newFile(this.tile.getFileCachePath());
671 if (cacheFile == null)
673 String msg = Logging.getMessage("generic.CantCreateCacheFile", this.tile.getFileCachePath());
674 Logging.logger().fine(msg);
675 return null;
678 if (cacheFile.exists())
679 return buffer; // info is already here; don't need to do anything
681 if (buffer != null)
683 WWIO.saveBuffer(buffer, cacheFile);
684 this.layer.firePropertyChange(AVKey.LAYER, null, this);
685 return buffer;
689 catch (java.io.IOException e)
691 Logging.logger().log(Level.FINE, Logging.getMessage(
692 "layers.PlaceNameLayer.ExceptionSavingRetrievedFile", this.tile.getFileCachePath()), e);
695 return null;
699 private static class GMLPlaceNameSAXHandler extends org.xml.sax.helpers.DefaultHandler
701 static final String GML_FEATURE_MEMBER = "gml:featureMember";
702 static final String TOPP_FULL_NAME_ND = "topp:full_name_nd";
703 static final String TOPP_LATITUDE = "topp:latitude";
704 static final String TOPP_LONGITUDE = "topp:longitude";
705 final LinkedList<String> internedQNameStack = new LinkedList<String>();
706 boolean inBeginEndPair = false;
707 StringBuilder latBuffer = new StringBuilder();
708 StringBuilder lonBuffer = new StringBuilder();
710 StringBuilder textArray = new StringBuilder();
711 int[] textIndexArray = new int[16];
712 double[] latlonArray = new double[16];
713 int numEntries = 0;
715 GMLPlaceNameSAXHandler()
719 PlaceNameChunk createPlaceNameChunk(PlaceNameService service)
721 return new PlaceNameChunk(service, this.textArray, this.textIndexArray, this.latlonArray, this.numEntries);
724 void beginEntry()
726 int textIndex = this.textArray.length();
727 this.textIndexArray = append(this.textIndexArray, this.numEntries, textIndex);
728 this.inBeginEndPair = true;
731 void endEntry()
733 double lat = this.parseDouble(this.latBuffer);
734 double lon = this.parseDouble(this.lonBuffer);
735 int numLatLon = 2 * this.numEntries;
736 this.latlonArray = this.append(this.latlonArray, numLatLon, lat);
737 numLatLon++;
738 this.latlonArray = this.append(this.latlonArray, numLatLon, lon);
740 this.latBuffer.delete(0, this.latBuffer.length());
741 this.lonBuffer.delete(0, this.lonBuffer.length());
742 this.inBeginEndPair = false;
743 this.numEntries++;
746 double parseDouble(StringBuilder sb)
748 double value = 0;
751 value = Double.parseDouble(sb.toString());
753 catch (NumberFormatException e)
755 Logging.logger().log(Level.FINE,
756 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", ""), e);
758 return value;
761 int[] append(int[] array, int index, int value)
763 if (index >= array.length)
764 array = this.resizeArray(array);
765 array[index] = value;
766 return array;
769 int[] resizeArray(int[] oldArray)
771 int newSize = 2 * oldArray.length;
772 int[] newArray = new int[newSize];
773 System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
774 return newArray;
777 double[] append(double[] array, int index, double value)
779 if (index >= array.length)
780 array = this.resizeArray(array);
781 array[index] = value;
782 return array;
785 double[] resizeArray(double[] oldArray)
787 int newSize = 2 * oldArray.length;
788 double[] newArray = new double[newSize];
789 System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
790 return newArray;
793 public void characters(char ch[], int start, int length)
795 if (!this.inBeginEndPair)
796 return;
798 // Top of QName stack is an interned string,
799 // so we can use pointer comparison.
800 String internedTopQName = this.internedQNameStack.getFirst();
802 StringBuilder sb = null;
803 if (TOPP_LATITUDE == internedTopQName)
804 sb = this.latBuffer;
805 else if (TOPP_LONGITUDE == internedTopQName)
806 sb = this.lonBuffer;
807 else if (TOPP_FULL_NAME_ND == internedTopQName)
808 sb = this.textArray;
810 if (sb != null)
811 sb.append(ch, start, length);
814 public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes)
816 // Don't validate uri, localName or attributes because they aren't used.
817 // Intern the qName string so we can use pointer comparison.
818 String internedQName = qName.intern();
819 if (GML_FEATURE_MEMBER == internedQName)
820 this.beginEntry();
821 this.internedQNameStack.addFirst(internedQName);
824 public void endElement(String uri, String localName, String qName)
826 // Don't validate uri or localName because they aren't used.
827 // Intern the qName string so we can use pointer comparison.
828 String internedQName = qName.intern();
829 if (GML_FEATURE_MEMBER == internedQName)
830 this.endEntry();
831 this.internedQNameStack.removeFirst();
835 private boolean loadTile(Tile tile, java.net.URL url)
837 PlaceNameChunk placeNameChunk = readTile(tile, url);
838 if (placeNameChunk == null)
839 return false;
841 this.memoryCache.add(tile, placeNameChunk);
842 return true;
845 private static PlaceNameChunk readTile(Tile tile, java.net.URL url)
847 java.io.InputStream is = null;
851 String path = url.getFile();
852 path = path.replaceAll("%20", " "); // TODO: find a better way to get a path usable by FileInputStream
854 java.io.FileInputStream fis = new java.io.FileInputStream(path);
855 java.io.BufferedInputStream buf = new java.io.BufferedInputStream(fis);
856 is = new java.util.zip.GZIPInputStream(buf);
858 GMLPlaceNameSAXHandler handler = new GMLPlaceNameSAXHandler();
859 javax.xml.parsers.SAXParserFactory.newInstance().newSAXParser().parse(is, handler);
860 return handler.createPlaceNameChunk(tile.getPlaceNameService());
862 catch (Exception e)
864 Logging.logger().log(Level.FINE,
865 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url.toString()), e);
867 finally
871 if (is != null)
872 is.close();
874 catch (java.io.IOException e)
876 Logging.logger().log(Level.FINE,
877 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url.toString()), e);
881 return null;
884 private void requestTile(Queue<Tile> queue, Tile tile)
886 if (tile.getPlaceNameService().isResourceAbsent(tile.getPlaceNameService().getTileNumber(
887 tile.row, tile.column)))
888 return;
889 if (!queue.contains(tile))
890 queue.offer(tile);
893 private void sendRequests()
895 Tile tile;
896 // Send threaded read tasks.
897 while (!WorldWind.getTaskService().isFull() && (tile = this.readQueue.poll()) != null)
899 WorldWind.getTaskService().addTask(new RequestTask(this, tile));
901 // Send retriever tasks.
902 while (!WorldWind.getRetrievalService().isFull() && (tile = this.downloadQueue.poll()) != null)
904 java.net.URL url;
907 url = tile.getRequestURL();
909 catch (java.net.MalformedURLException e)
911 String message = Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToDownloadFile", tile);
912 Logging.logger().log(Level.FINE, message, e);
913 return;
915 WorldWind.getRetrievalService().runRetriever(new HTTPRetriever(url, new DownloadPostProcessor(this, tile)));