placenamelayer.java

来自「world wind java sdk 源码」· Java 代码 · 共 1,493 行 · 第 1/4 页

JAVA
1,493
字号
            // Don't validate uri or localName because they aren't used.
            // Intern the qName string so we can use pointer comparison.
            String internedQName = qName.intern();
            //noinspection StringEquality
            if (GML_FEATURE_MEMBER == internedQName)
                this.endEntry();
            this.internedQNameStack.removeFirst();
        }
    }

    private void downloadTile(final Tile tile)
    {
        downloadTile(tile, null);
    }

    private void downloadTile(final Tile tile, DownloadPostProcessor postProcessor)
    {
        if (!this.isNetworkRetrievalEnabled())
            return;
        
        if (!WorldWind.getRetrievalService().isAvailable())
            return;

        java.net.URL url;
        try
        {
            url = tile.getRequestURL();
            if (WorldWind.getNetworkStatus().isHostUnavailable(url))
                return;
        }
        catch (java.net.MalformedURLException e)
        {
            Logging.logger().log(java.util.logging.Level.SEVERE,
                    Logging.getMessage("layers.PlaceNameLayer.ExceptionCreatingUrl", tile), e);
            return;
        }

        Retriever retriever;

        if ("http".equalsIgnoreCase(url.getProtocol()) || "https".equalsIgnoreCase(url.getProtocol()))
        {
            if (postProcessor == null)
                postProcessor = new DownloadPostProcessor(this, tile);
            retriever = new HTTPRetriever(url, postProcessor);
        }
        else
        {
            Logging.logger().severe(
                    Logging.getMessage("layers.PlaceNameLayer.UnknownRetrievalProtocol", url.toString()));
            return;
        }

        // Apply any overridden timeouts.
        Integer cto = AVListImpl.getIntegerValue(this, AVKey.URL_CONNECT_TIMEOUT);
        if (cto != null && cto > 0)
            retriever.setConnectTimeout(cto);
        Integer cro = AVListImpl.getIntegerValue(this, AVKey.URL_READ_TIMEOUT);
        if (cro != null && cro > 0)
            retriever.setReadTimeout(cro);
        Integer srl = AVListImpl.getIntegerValue(this, AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT);
        if (srl != null && srl > 0)
            retriever.setStaleRequestLimit(srl);

        WorldWind.getRetrievalService().runRetriever(retriever, tile.getPriority());
    }

    private void saveBuffer(java.nio.ByteBuffer buffer, java.io.File outFile) throws java.io.IOException
    {
        synchronized (this.fileLock) // sychronized with read of file in RequestTask.run()
        {
            WWIO.saveBuffer(buffer, outFile);
        }
    }

    private static class DownloadPostProcessor implements RetrievalPostProcessor
    {
        final PlaceNameLayer layer;
        final Tile tile;

        private DownloadPostProcessor(PlaceNameLayer layer, Tile tile)
        {
            this.layer = layer;
            this.tile = tile;
        }

        public java.nio.ByteBuffer run(Retriever retriever)
        {
            if (retriever == null)
            {
                String msg = Logging.getMessage("nullValue.RetrieverIsNull");
                Logging.logger().fine(msg);
                throw new IllegalArgumentException(msg);
            }

            try
            {
                if (!retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL))
                    return null;

                URLRetriever r = (URLRetriever) retriever;
                ByteBuffer buffer = r.getBuffer();

                if (retriever instanceof HTTPRetriever)
                {
                    HTTPRetriever htr = (HTTPRetriever) retriever;
                    if (htr.getResponseCode() == java.net.HttpURLConnection.HTTP_NO_CONTENT)
                    {
                        // Mark tile as missing to avoid further attempts
                        tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
                            tile.column));
                        return null;
                    }
                    else if (htr.getResponseCode() != java.net.HttpURLConnection.HTTP_OK)
                    {
                        // Also mark tile as missing, but for an unknown reason.
                        tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
                            tile.column));
                        return null;
                    }
                }

                final java.io.File outFile = WorldWind.getDataFileStore().newFile(this.tile.getFileCachePath());
                if (outFile == null)
                    return null;

                if (outFile.exists())
                    return buffer; // info is already here; don't need to do anything

                if (buffer != null)
                {
                    String contentType = retriever.getContentType();
                    if (contentType == null)
                    {
                        // TODO: logger message
                        return null;
                    }

                    this.layer.saveBuffer(buffer, outFile);
                    this.layer.firePropertyChange(AVKey.LAYER, null, this);
                    return buffer;
                }
            }
            catch (ClosedByInterruptException e)
            {
                Logging.logger().log(java.util.logging.Level.FINE,
                    Logging.getMessage("generic.OperationCancelled", "placename retrieval"), e);
            }
            catch (java.io.IOException e)
            {
                tile.getPlaceNameService().markResourceAbsent(tile.getPlaceNameService().getTileNumber(tile.row,
                    tile.column));
                Logging.logger().log(Level.FINE, Logging.getMessage(
                    "layers.PlaceNameLayer.ExceptionSavingRetrievedFile", this.tile.getFileCachePath()), e);
            }
            
            return null;
        }
    }

    // *** Bulk download ***
    // *** Bulk download ***
    // *** Bulk download ***
    private static final long AVG_TILE_SIZE = 8*1024;
    /**
     * Start a new {@link gov.nasa.worldwind.retrieve.BulkRetrievalThread} that will try to download all place name
     * tiles for a given {@link Sector} and resolution. Note that the target resolution is ignored right now.
     *
     * @param sector the {@link Sector} to download tiles for.
     * @param resolution the target resolution - ignored.
     * @return the {@link gov.nasa.worldwind.retrieve.BulkRetrievalThread} that executes the retrieval.
     */
    public BulkRetrievalThread makeLocal(Sector sector, double resolution)
    {
        BulkTileDownloadThread thread = new BulkTileDownloadThread(this, sector, resolution);
        thread.setDaemon(true);
        thread.start();
        return thread;
    }

    /**
     * Get the estimated size in byte of the missing data for the given {@link Sector}
     * and resolution. Note that the target resolution must be provided in radian latitude per
     * data sample - which is the resolution in meter divided by the globe radius.
     *
     * @param sector the {@link Sector} to estimate.
     * @param resolution the target resolution provided in radian latitude per texel.
     * @return the estimated size in byte of the missing imagery.
     */
    public long getEstimatedMissingDataSize(Sector sector, double resolution)
    {
        int tileCount;
        try
        {
            tileCount=this.getMissingTilesCountEstimate(sector, resolution);
        }
        catch (Exception e)
        {
            String message = Logging.getMessage("generic.ExceptionDuringDataSizeEstimate", this.getName());
            Logging.logger().severe(message);
            throw new RuntimeException(message);
        }
        return tileCount * AVG_TILE_SIZE;
    }

    private class BulkTileDownloadThread extends BulkRetrievalThread
    {
        private int MAX_TILE_COUNT_PER_REGION = 200;

        private final PlaceNameLayer layer;
        private ArrayList<Tile> missingTiles;

        public BulkTileDownloadThread(PlaceNameLayer layer, Sector sector, double resolution)
        {
            //resolution is compared to the maxDsiatnce value in each placenameservice
            super(layer, sector, resolution);
            this.layer = layer;
        }

        public void run()
        {
            try
            {
                // Cycle though placenameservices and find missing tiles
                missingTiles = new ArrayList<Tile>();
                ArrayList<Tile> allMissingTiles =layer.getMissingTilesInSector(this.sector, this.resolution);

                this.progress.setTotalCount(allMissingTiles.size());
                // Submit missing tiles requests at 10 sec intervals
                while (allMissingTiles.size() > 0)
                {
                    transferMissingTiles(allMissingTiles, missingTiles, MAX_TILE_COUNT_PER_REGION);

                    while (missingTiles.size() > 0)
                    {
                        submitMissingTilesRequests();
                        if (missingTiles.size() > 0)
                            Thread.sleep(RETRIEVAL_SERVICE_POLL_DELAY);
                    }
                }
            }
            catch (InterruptedException e)
            {
                String message = Logging.getMessage("generic.BulkRetrievalInterrupted", layer.getName());
                Logging.logger().log(java.util.logging.Level.WARNING, message, e);
            }
            catch (Exception e)
            {
                String message = Logging.getMessage("generic.ExceptionDuringBulkRetrieval", layer.getName());
                Logging.logger().severe(message);
                throw new RuntimeException(message);
            }
        }

        private void transferMissingTiles(ArrayList<Tile> source, ArrayList<Tile> destination, int maxCount)
        {
            int i = 0;
            while (i < maxCount && source.size() > 0)
            {
                destination.add(source.remove(0));
                i++;
            }
        }

        private synchronized void submitMissingTilesRequests() throws InterruptedException
        {
            RetrievalService rs = WorldWind.getRetrievalService();
            int i = 0;
            while (this.missingTiles.size() > i && rs.isAvailable())
            {
                Thread.sleep(1); // generates InterruptedException if thread has been interrupted

                Tile tile = this.missingTiles.get(i);
                if (tile.isTileLocalOrAbsent())
                {
                    // No need to request that tile anymore
                    this.missingTiles.remove(i);
                }
                else
                {
                    layer.downloadTile(tile, new BulkDownloadPostProcessor(layer, tile));
                    i++;
                }
            }
        }

        private class BulkDownloadPostProcessor extends DownloadPostProcessor
        {
            public BulkDownloadPostProcessor(PlaceNameLayer layer, Tile tile)
            {
                super(layer, tile);
            }

            public ByteBuffer run(Retriever retriever)
            {
                ByteBuffer buffer = super.run(retriever);
                if (buffer != null)
                    removeRetrievedTile(this.tile);

                return buffer;
            }
        }

        private synchronized void removeRetrievedTile(Tile tile)
        {
            this.missingTiles.remove(tile);
            this.progress.setCurrentCount(this.progress.getCurrentCount() + 1);
            this.progress.setCurrentSize(this.progress.getCurrentSize() + AVG_TILE_SIZE);
            this.progress.setLastUpdateTime(System.currentTimeMillis());
            // Estimate total size
            this.progress.setTotalSize(
            this.progress.getCurrentSize() / this.progress.getCurrentCount() * this.progress.getTotalCount());
        }
    }

    private int getMissingTilesCountEstimate(Sector sector, double resolution)
    {
        int tileCount=0;
        int serviceCount = this.placeNameServiceSet.getServiceCount();
        for (int i = 0; i < serviceCount; i++)
        {
            int serviceTileCount=0;
            PlaceNameService service = this.getPlaceNameServiceSet().getService(i);
             if (service.getMaxDisplayDistance() > resolution)
             {
                 NavigationTile navTile = this.navTiles.get(i);
                 // drill down into tiles to find bottom level navTiles visible
                 List<NavigationTile> list = navTile.navTilesVisible(sector);
                 for(NavigationTile nt: list)
                 {
                     serviceTileCount +=  nt.estimateNumberTilesinSector(sector);
                 }
            }

            tileCount += serviceTileCount;
        }

        return tileCount;
    }
    
    private ArrayList<Tile> getMissingTilesInSector(Sector sector, double resolution) throws InterruptedException
    {
        ArrayList<Tile> allMissingTiles =new ArrayList<Tile>();
        int serviceCount = this.placeNameServiceSet.getServiceCount();
        for (int i = 0; i < serviceCount; i++)
        {
             PlaceNameService service = this.getPlaceNameServiceSet().getService(i);
             if (service.getMaxDisplayDistance() > resolution)
             {
                 // get tiles in sector
                 ArrayList<Tile> baseTiles = new ArrayList<Tile>();

                 NavigationTile navTile = this.navTiles.get(i);
                 // drill down into tiles to find bottom level navTiles visible
                 List<NavigationTile> list = navTile.navTilesVisible(sector);
                 for(NavigationTile nt: list)
                 {
                     baseTiles.addAll(nt.getTiles());
                 }

                for (Tile tile : baseTiles)
                {
                    if ((tile.getSector().intersects(sector)) && (!tile.isTileLocalOrAbsent()))
                        allMissingTiles.add(tile);
                }
            }
        }

        return allMissingTiles;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?