001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.data.imagery.vectortile.mapbox; 003 004import java.util.concurrent.ThreadPoolExecutor; 005 006import org.openstreetmap.gui.jmapviewer.Tile; 007import org.openstreetmap.gui.jmapviewer.interfaces.CachedTileLoader; 008import org.openstreetmap.gui.jmapviewer.interfaces.TileJob; 009import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader; 010import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 011import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 012import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 013import org.openstreetmap.josm.data.cache.JCSCachedTileLoaderJob; 014import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader; 015import org.openstreetmap.josm.data.imagery.TileJobOptions; 016import org.openstreetmap.josm.data.preferences.IntegerProperty; 017import org.openstreetmap.josm.tools.CheckParameterUtil; 018 019import org.apache.commons.jcs3.access.behavior.ICacheAccess; 020 021/** 022 * A TileLoader class for MVT tiles 023 * @author Taylor Smock 024 * @since 17862 025 */ 026public class MapboxVectorCachedTileLoader implements TileLoader, CachedTileLoader { 027 protected final ICacheAccess<String, BufferedImageCacheEntry> cache; 028 protected final TileLoaderListener listener; 029 protected final TileJobOptions options; 030 private static final IntegerProperty THREAD_LIMIT = 031 new IntegerProperty("imagery.vector.mvtloader.maxjobs", TMSCachedTileLoader.THREAD_LIMIT.getDefaultValue()); 032 private static final ThreadPoolExecutor DEFAULT_DOWNLOAD_JOB_DISPATCHER = 033 TMSCachedTileLoader.getNewThreadPoolExecutor("MVT-downloader-%d", THREAD_LIMIT.get()); 034 035 /** 036 * Constructor 037 * @param listener called when tile loading has finished 038 * @param cache of the cache 039 * @param options tile job options 040 */ 041 public MapboxVectorCachedTileLoader(TileLoaderListener listener, ICacheAccess<String, BufferedImageCacheEntry> cache, 042 TileJobOptions options) { 043 CheckParameterUtil.ensureParameterNotNull(cache, "cache"); 044 this.cache = cache; 045 this.options = options; 046 this.listener = listener; 047 } 048 049 @Override 050 public void clearCache(TileSource source) { 051 this.cache.remove(source.getName() + ':'); 052 } 053 054 @Override 055 public TileJob createTileLoaderJob(Tile tile) { 056 return new MapboxVectorCachedTileLoaderJob( 057 listener, 058 tile, 059 cache, 060 options, 061 getDownloadExecutor()); 062 } 063 064 @Override 065 public void cancelOutstandingTasks() { 066 final ThreadPoolExecutor executor = getDownloadExecutor(); 067 executor.getQueue().stream().filter(executor::remove).filter(MapboxVectorCachedTileLoaderJob.class::isInstance) 068 .map(MapboxVectorCachedTileLoaderJob.class::cast).forEach(JCSCachedTileLoaderJob::handleJobCancellation); 069 } 070 071 @Override 072 public boolean hasOutstandingTasks() { 073 return getDownloadExecutor().getTaskCount() > getDownloadExecutor().getCompletedTaskCount(); 074 } 075 076 private static ThreadPoolExecutor getDownloadExecutor() { 077 return DEFAULT_DOWNLOAD_JOB_DISPATCHER; 078 } 079}