/*******************************************************************************
* Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com)
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License 3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl.html
*
******************************************************************************/
package com.opendoorlogistics.core.gis.map.background;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.ResponseCache;
import java.util.HashMap;
import java.util.Properties;
import org.mapsforge.map.reader.MapDataStore;
import com.opendoorlogistics.codefromweb.jxmapviewer2.ExpiringOSMLocalResponseCache;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.OSMTileFactoryInfo;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.Tile;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.TileFactory;
import com.opendoorlogistics.codefromweb.jxmapviewer2.fork.swingx.mapviewer.TileFactoryInfo;
import com.opendoorlogistics.core.AppConstants;
import com.opendoorlogistics.core.gis.map.background.BackgroundMapConfig.BackgroundType;
import com.opendoorlogistics.core.utils.Colours;
import com.opendoorlogistics.core.utils.PropertiesUtils;
import com.opendoorlogistics.core.utils.images.ImageUtils;
public final class BackgroundTileFactorySingleton {
private static final ODLTileFactory SINGLETON;
private static final ExpiringOSMLocalResponseCache LOCAL_RESPONSE_CACHE;
private static final TileFactoryCache FADELESS_TILE_FACTORY_CACHE = new TileFactoryCache();
private BackgroundTileFactorySingleton() {
}
public static ODLTileFactory getFactory() {
return SINGLETON;
}
static {
// always ensure we initialise the local file cache
File cacheDir = new File(System.getProperty("user.home") + File.separator + ".jxmapviewer2");
LOCAL_RESPONSE_CACHE = new ExpiringOSMLocalResponseCache( cacheDir, false);
ResponseCache.setDefault(LOCAL_RESPONSE_CACHE);
// Read properties and create default background map
Properties p = PropertiesUtils.loadFromFile(new File(AppConstants.ODL_BACKGROUND_MAP_PROPERTIES_FILE));
BackgroundMapConfig c = new BackgroundMapConfig(p);
SINGLETON = createTileFactory(c);
}
public static ODLTileFactory createTileFactory(BackgroundMapConfig config){
// Create config copy without the fade
BackgroundMapConfig deepCopy = new BackgroundMapConfig(config);
deepCopy.setFade(null);
// Try to get factory from the fadeless-cache
ODLTileFactory noFade= FADELESS_TILE_FACTORY_CACHE.get(deepCopy);
// Create factory without the fade if needed
if(noFade==null){
TileFactory tileFactory = createFactory(deepCopy);
if(tileFactory!=null){
noFade = new TileFactory2ODL(tileFactory, true, null);
FADELESS_TILE_FACTORY_CACHE.put(deepCopy, noFade);
// ensure its cached properly on-disk
if(deepCopy.getType() == BackgroundType.OSMTILESERVER){
LOCAL_RESPONSE_CACHE.addAcceptedBasedURL(deepCopy.getTileserverUrl());
}
}
}
if(noFade!=null){
return new ODLTileFactoryDecorator(noFade, config.getFade());
}
return null;
}
private static class EmptyTileFactory extends TileFactory {
final BufferedImage blankImage;
EmptyTileFactory(TileFactoryInfo info, BackgroundMapConfig config) {
super(info);
Color colour = Color.WHITE;
if (config.getFade() != null && config.getFade().getColour() != null) {
colour = Colours.lerp(Color.WHITE, config.getFade().getColour(), config.getFade().getColour().getAlpha() / 255.0);
}
blankImage = ImageUtils.createBlankImage(256, 256, BufferedImage.TYPE_INT_ARGB, colour);
}
@Override
public BufferedImage renderSynchronously(int x, int y, int zoom) {
return blankImage;
}
@Override
public Tile getTile(int x, int y, int zoom) {
Tile ret = new Tile(x, y, zoom) {
@Override
public boolean isLoaded() {
return true;
}
@Override
public boolean isLoading() {
return false;
}
@Override
public BufferedImage getImage() {
return blankImage;
}
};
return ret;
}
@Override
public void dispose() {
// TODO Auto-generated method stub
}
@Override
protected void startLoading(Tile tile) {
// TODO Auto-generated method stub
}
@Override
public boolean isRenderedOffline() {
return true;
}
}
private static TileFactory createFactory(BackgroundMapConfig config) {
TileFactoryInfo info = new OSMTileFactoryInfo(config.getTileserverUrl());
BackgroundType type = config.getType();
if (type == BackgroundType.MAPSFORGE) {
MapDataStore result = MapsforgeTileFactory.openMapsforgeDb(config.getMapsforgeFilename());
if (result != null) {
return new MapsforgeTileFactory(info, config.getMapsforgeXMLRenderTheme(), result, config.getFade());
}
type = BackgroundType.EMPTY;
}
if (type == BackgroundType.OSMTILESERVER) {
return new ODLWebTileFactory(info, config.getFade());
}
// return empty tile factory...
return new EmptyTileFactory(new OSMTileFactoryInfo(), config);
}
// public static void main(String[]args){
// System.out.println(BackgroundTileFactorySingleton.getFactory());
// }
private static class TileFactoryCache {
private HashMap<BackgroundMapConfig, ODLTileFactory> cached = new HashMap<BackgroundMapConfig, ODLTileFactory>();
public synchronized void put(BackgroundMapConfig config, ODLTileFactory factory) {
checkNoFade(config);
ODLTileFactory pre = get(config);
if (pre != null) {
pre.dispose();
}
cached.put(config, factory);
}
private void checkNoFade(BackgroundMapConfig config) {
if (config.getFade() != null) {
throw new IllegalArgumentException("Fade cannot be set on a cached tile factory; fade should be applied afterwards");
}
}
public synchronized ODLTileFactory get(BackgroundMapConfig config) {
checkNoFade(config);
return cached.get(config);
}
public synchronized void clear() {
for (ODLTileFactory factory : cached.values()) {
factory.dispose();
}
cached.clear();
}
}
public static void dispose(){
FADELESS_TILE_FACTORY_CACHE.clear();
}
}