Updated to worldwind release 20070817
[worldwind-tracker.git] / gov / nasa / worldwind / layers / placename / PlaceNameLayer.java
blob1e02c892b9130775545bc27077a6606e2ea116b6
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 2490 2007-08-02 18:24:12Z dcollins $
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 protected void doRender(DrawContext dc)
424 boolean enableDepthTest = this.isEnableDepthTest(dc);
426 int serviceCount = this.placeNameServiceSet.getServiceCount();
427 for (int i = 0; i < serviceCount; i++)
429 PlaceNameService placeNameService = this.placeNameServiceSet.getService(i);
430 if (!isServiceVisible(dc, placeNameService))
431 continue;
433 double minDist = placeNameService.getMinDisplayDistance();
434 double maxDist = placeNameService.getMaxDisplayDistance();
435 double minDistSquared = minDist * minDist;
436 double maxDistSquared = maxDist * maxDist;
438 Tile[] tiles = this.tiles.get(i);
439 for (Tile tile : tiles)
443 drawOrRequestTile(dc, tile, minDistSquared, maxDistSquared, enableDepthTest);
445 catch (Exception e)
447 Logging.logger().log(Level.FINE, Logging.getMessage("layers.PlaceNameLayer.ExceptionRenderingTile"),
453 this.sendRequests();
456 private boolean isEnableDepthTest(DrawContext dc)
458 Position eyePos = dc.getView().getEyePosition();
459 if (eyePos == null)
460 return false;
462 double altitude = eyePos.getElevation();
463 return altitude < (dc.getVerticalExaggeration() * dc.getGlobe().getMaxElevation());
466 private void drawOrRequestTile(DrawContext dc, Tile tile, double minDisplayDistanceSquared,
467 double maxDisplayDistanceSquared, boolean enableDepthTest)
469 if (!isTileVisible(dc, tile, minDisplayDistanceSquared, maxDisplayDistanceSquared))
470 return;
472 Object cacheObj = this.memoryCache.getObject(tile);
473 if (cacheObj == null)
475 this.requestTile(this.readQueue, tile);
476 return;
479 if (!(cacheObj instanceof PlaceNameChunk))
480 return;
482 PlaceNameChunk placeNameChunk = (PlaceNameChunk) cacheObj;
483 Iterator<PlaceName> renderIter = placeNameChunk.createRenderIterator(dc);
484 placeNameRenderer.render(dc, renderIter, enableDepthTest);
487 private static boolean isServiceVisible(DrawContext dc, PlaceNameService placeNameService)
489 if (!placeNameService.isEnabled())
490 return false;
491 //noinspection SimplifiableIfStatement
492 if (dc.getVisibleSector() != null && !placeNameService.getSector().intersects(dc.getVisibleSector()))
493 return false;
495 return placeNameService.getExtent(dc).intersects(dc.getView().getFrustumInModelCoordinates());
498 private static boolean isTileVisible(DrawContext dc, Tile tile, double minDistanceSquared,
499 double maxDistanceSquared)
501 if (!tile.getSector().intersects(dc.getVisibleSector()))
502 return false;
504 View view = dc.getView();
505 Position eyePos = view.getEyePosition();
506 if (eyePos == null)
507 return false;
509 Angle lat = clampAngle(eyePos.getLatitude(), tile.getSector().getMinLatitude(),
510 tile.getSector().getMaxLatitude());
511 Angle lon = clampAngle(eyePos.getLongitude(), tile.getSector().getMinLongitude(),
512 tile.getSector().getMaxLongitude());
513 Vec4 p = dc.getGlobe().computePointFromPosition(lat, lon, 0d);
514 double distSquared = dc.getView().getEyePoint().distanceToSquared3(p);
515 //noinspection RedundantIfStatement
516 if (minDistanceSquared > distSquared || maxDistanceSquared < distSquared)
517 return false;
519 return true;
522 private static boolean isNameVisible(DrawContext dc, PlaceNameService service, Position namePosition)
524 double elevation = dc.getVerticalExaggeration() * namePosition.getElevation();
525 Vec4 namePoint = dc.getGlobe().computePointFromPosition(namePosition.getLatitude(),
526 namePosition.getLongitude(), elevation);
527 Vec4 eyeVec = dc.getView().getEyePoint();
529 double dist = eyeVec.distanceTo3(namePoint);
530 return dist >= service.getMinDisplayDistance() && dist <= service.getMaxDisplayDistance();
533 private static Angle clampAngle(Angle a, Angle min, Angle max)
535 return a.compareTo(min) < 0 ? min : (a.compareTo(max) > 0 ? max : a);
538 // ============== Image Reading and Downloading ======================= //
539 // ============== Image Reading and Downloading ======================= //
540 // ============== Image Reading and Downloading ======================= //
542 private static final int MAX_REQUESTS = 64;
543 private final Queue<Tile> downloadQueue = new LinkedBlockingQueue<Tile>(MAX_REQUESTS);
544 private final Queue<Tile> readQueue = new LinkedBlockingQueue<Tile>(MAX_REQUESTS);
546 private static class RequestTask implements Runnable
548 final PlaceNameLayer layer;
549 final Tile tile;
551 RequestTask(PlaceNameLayer layer, Tile tile)
553 this.layer = layer;
554 this.tile = tile;
557 @Override
558 public boolean equals(Object o)
560 if (this == o)
561 return true;
562 if (o == null || this.getClass() != o.getClass())
563 return false;
565 final RequestTask other = (RequestTask) o;
567 // Don't include layer in comparison so that requests are shared among layers
568 return !(this.tile != null ? !this.tile.equals(other.tile) : other.tile != null);
571 @Override
572 public int hashCode()
574 return (this.tile != null ? this.tile.hashCode() : 0);
577 public void run()
579 synchronized (tile)
581 if (this.layer.memoryCache.getObject(this.tile) != null)
582 return;
584 final java.net.URL tileURL = WorldWind.getDataFileCache().findFile(tile.getFileCachePath(), false);
585 if (tileURL != null)
587 if (this.layer.loadTile(this.tile, tileURL))
589 tile.getPlaceNameService().unmarkResourceAbsent(tile.getPlaceNameService().getTileNumber(
590 tile.row,
591 tile.column));
592 this.layer.firePropertyChange(AVKey.LAYER, null, this);
594 else
596 // Assume that something's wrong with the file and delete it.
597 WorldWind.getDataFileCache().removeFile(tileURL);
598 tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
599 tile.column));
600 String message = Logging.getMessage("generic.DeletedCorruptDataFile", tileURL);
601 Logging.logger().fine(message);
603 return;
607 this.layer.requestTile(this.layer.downloadQueue, this.tile);
610 public String toString()
612 return this.tile.toString();
616 private static class DownloadPostProcessor implements RetrievalPostProcessor
618 final PlaceNameLayer layer;
619 final Tile tile;
621 private DownloadPostProcessor(PlaceNameLayer layer, Tile tile)
623 this.layer = layer;
624 this.tile = tile;
627 public java.nio.ByteBuffer run(Retriever retriever)
629 if (retriever == null)
631 String msg = Logging.getMessage("nullValue.RetrieverIsNull");
632 Logging.logger().fine(msg);
633 throw new IllegalArgumentException(msg);
636 if (!retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL))
637 return null;
639 if (!(retriever instanceof URLRetriever))
640 return null;
644 if (retriever instanceof HTTPRetriever)
646 HTTPRetriever httpRetriever = (HTTPRetriever) retriever;
647 if (httpRetriever.getResponseCode() == java.net.HttpURLConnection.HTTP_NO_CONTENT)
649 // Mark tile as missing to avoid further attempts
650 tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
651 tile.column));
652 return null;
656 URLRetriever urlRetriever = (URLRetriever) retriever;
657 java.nio.ByteBuffer buffer = urlRetriever.getBuffer();
659 synchronized (tile)
661 final java.io.File cacheFile = WorldWind.getDataFileCache().newFile(this.tile.getFileCachePath());
662 if (cacheFile == null)
664 String msg = Logging.getMessage("generic.CantCreateCacheFile", this.tile.getFileCachePath());
665 Logging.logger().fine(msg);
666 return null;
669 if (cacheFile.exists())
670 return buffer; // info is already here; don't need to do anything
672 if (buffer != null)
674 WWIO.saveBuffer(buffer, cacheFile);
675 this.layer.firePropertyChange(AVKey.LAYER, null, this);
676 return buffer;
680 catch (java.io.IOException e)
682 Logging.logger().log(Level.FINE, Logging.getMessage(
683 "layers.PlaceNameLayer.ExceptionSavingRetrievedFile", this.tile.getFileCachePath()), e);
686 return null;
690 private static class GMLPlaceNameSAXHandler extends org.xml.sax.helpers.DefaultHandler
692 static final String GML_FEATURE_MEMBER = "gml:featureMember";
693 static final String TOPP_FULL_NAME_ND = "topp:full_name_nd";
694 static final String TOPP_LATITUDE = "topp:latitude";
695 static final String TOPP_LONGITUDE = "topp:longitude";
696 final LinkedList<String> internedQNameStack = new LinkedList<String>();
697 boolean inBeginEndPair = false;
698 StringBuilder latBuffer = new StringBuilder();
699 StringBuilder lonBuffer = new StringBuilder();
701 StringBuilder textArray = new StringBuilder();
702 int[] textIndexArray = new int[16];
703 double[] latlonArray = new double[16];
704 int numEntries = 0;
706 GMLPlaceNameSAXHandler()
710 PlaceNameChunk createPlaceNameChunk(PlaceNameService service)
712 return new PlaceNameChunk(service, this.textArray, this.textIndexArray, this.latlonArray, this.numEntries);
715 void beginEntry()
717 int textIndex = this.textArray.length();
718 this.textIndexArray = append(this.textIndexArray, this.numEntries, textIndex);
719 this.inBeginEndPair = true;
722 void endEntry()
724 double lat = this.parseDouble(this.latBuffer);
725 double lon = this.parseDouble(this.lonBuffer);
726 int numLatLon = 2 * this.numEntries;
727 this.latlonArray = this.append(this.latlonArray, numLatLon, lat);
728 numLatLon++;
729 this.latlonArray = this.append(this.latlonArray, numLatLon, lon);
731 this.latBuffer.delete(0, this.latBuffer.length());
732 this.lonBuffer.delete(0, this.lonBuffer.length());
733 this.inBeginEndPair = false;
734 this.numEntries++;
737 double parseDouble(StringBuilder sb)
739 double value = 0;
742 value = Double.parseDouble(sb.toString());
744 catch (NumberFormatException e)
746 Logging.logger().log(Level.FINE,
747 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", ""), e);
749 return value;
752 int[] append(int[] array, int index, int value)
754 if (index >= array.length)
755 array = this.resizeArray(array);
756 array[index] = value;
757 return array;
760 int[] resizeArray(int[] oldArray)
762 int newSize = 2 * oldArray.length;
763 int[] newArray = new int[newSize];
764 System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
765 return newArray;
768 double[] append(double[] array, int index, double value)
770 if (index >= array.length)
771 array = this.resizeArray(array);
772 array[index] = value;
773 return array;
776 double[] resizeArray(double[] oldArray)
778 int newSize = 2 * oldArray.length;
779 double[] newArray = new double[newSize];
780 System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
781 return newArray;
784 public void characters(char ch[], int start, int length)
786 if (!this.inBeginEndPair)
787 return;
789 // Top of QName stack is an interned string,
790 // so we can use pointer comparison.
791 String internedTopQName = this.internedQNameStack.getFirst();
793 StringBuilder sb = null;
794 if (TOPP_LATITUDE == internedTopQName)
795 sb = this.latBuffer;
796 else if (TOPP_LONGITUDE == internedTopQName)
797 sb = this.lonBuffer;
798 else if (TOPP_FULL_NAME_ND == internedTopQName)
799 sb = this.textArray;
801 if (sb != null)
802 sb.append(ch, start, length);
805 public void startElement(String uri, String localName, String qName, org.xml.sax.Attributes attributes)
807 // Don't validate uri, localName or attributes because they aren't used.
808 // Intern the qName string so we can use pointer comparison.
809 String internedQName = qName.intern();
810 if (GML_FEATURE_MEMBER == internedQName)
811 this.beginEntry();
812 this.internedQNameStack.addFirst(internedQName);
815 public void endElement(String uri, String localName, String qName)
817 // Don't validate uri or localName because they aren't used.
818 // Intern the qName string so we can use pointer comparison.
819 String internedQName = qName.intern();
820 if (GML_FEATURE_MEMBER == internedQName)
821 this.endEntry();
822 this.internedQNameStack.removeFirst();
826 private boolean loadTile(Tile tile, java.net.URL url)
828 PlaceNameChunk placeNameChunk = readTile(tile, url);
829 if (placeNameChunk == null)
830 return false;
832 this.memoryCache.add(tile, placeNameChunk);
833 return true;
836 private static PlaceNameChunk readTile(Tile tile, java.net.URL url)
838 java.io.InputStream is = null;
842 String path = url.getFile();
843 path = path.replaceAll("%20", " "); // TODO: find a better way to get a path usable by FileInputStream
845 java.io.FileInputStream fis = new java.io.FileInputStream(path);
846 java.io.BufferedInputStream buf = new java.io.BufferedInputStream(fis);
847 is = new java.util.zip.GZIPInputStream(buf);
849 GMLPlaceNameSAXHandler handler = new GMLPlaceNameSAXHandler();
850 javax.xml.parsers.SAXParserFactory.newInstance().newSAXParser().parse(is, handler);
851 return handler.createPlaceNameChunk(tile.getPlaceNameService());
853 catch (Exception e)
855 Logging.logger().log(Level.FINE,
856 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url.toString()), e);
858 finally
862 if (is != null)
863 is.close();
865 catch (java.io.IOException e)
867 Logging.logger().log(Level.FINE,
868 Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToReadFile", url.toString()), e);
872 return null;
875 private void requestTile(Queue<Tile> queue, Tile tile)
877 if (tile.getPlaceNameService().isResourceAbsent(tile.getPlaceNameService().getTileNumber(
878 tile.row, tile.column)))
879 return;
880 if (!queue.contains(tile))
881 queue.offer(tile);
884 private void sendRequests()
886 Tile tile;
887 // Send threaded read tasks.
888 while (!WorldWind.getTaskService().isFull() && (tile = this.readQueue.poll()) != null)
890 WorldWind.getTaskService().addTask(new RequestTask(this, tile));
892 // Send retriever tasks.
893 while (!WorldWind.getRetrievalService().isFull() && (tile = this.downloadQueue.poll()) != null)
895 java.net.URL url;
898 url = tile.getRequestURL();
900 catch (java.net.MalformedURLException e)
902 String message = Logging.getMessage("layers.PlaceNameLayer.ExceptionAttemptingToDownloadFile", tile);
903 Logging.logger().log(Level.FINE, message, e);
904 return;
906 WorldWind.getRetrievalService().runRetriever(new HTTPRetriever(url, new DownloadPostProcessor(this, tile)));