/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.maps; import org.mapsforge.map.layer.download.tilesource.OpenCycleMap; import org.mapsforge.map.layer.download.tilesource.OpenStreetMapMapnik; import org.mapsforge.map.rendertheme.ExternalRenderTheme; import slash.navigation.datasources.DataSource; import slash.navigation.datasources.DataSourceManager; import slash.navigation.datasources.Downloadable; import slash.navigation.download.Download; import slash.navigation.maps.helpers.ThemeForMapMediator; import slash.navigation.maps.impl.*; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.logging.Logger; import java.util.prefs.Preferences; import static java.lang.String.format; import static java.lang.System.currentTimeMillis; import static java.util.Arrays.sort; import static org.mapsforge.map.rendertheme.InternalRenderTheme.OSMARENDER; import static slash.common.io.Directories.ensureDirectory; import static slash.common.io.Directories.getApplicationDirectory; import static slash.common.io.Files.collectFiles; import static slash.common.io.Files.printArrayToDialogString; import static slash.navigation.maps.helpers.MapUtil.extractBoundingBox; import static slash.navigation.maps.helpers.MapUtil.removePrefix; /** * Manages {@link LocalMap}s and {@link LocalTheme}s * * @author Christian Pesch */ public class MapManager { private static final Logger log = Logger.getLogger(MapManager.class.getName()); private static final Preferences preferences = Preferences.userNodeForPackage(MapManager.class); private static final String MAP_DIRECTORY_PREFERENCE = "mapDirectory"; private static final String THEME_DIRECTORY_PREFERENCE = "themeDirectory"; private static final String DISPLAYED_MAP_PREFERENCE = "displayedMap"; private static final String APPLIED_THEME_PREFERENCE = "appliedTheme"; private static final String OSMARENDER_URL = "http://wiki.openstreetmap.org/wiki/Osmarender"; private static final String OPENSTREETMAP_URL = "http://www.openstreetmap.org/"; private final DataSourceManager dataSourceManager; private LocalMapsTableModel availableMapsModel = new LocalMapsTableModel(); private LocalThemesTableModel availableThemesModel = new LocalThemesTableModel(); private RemoteMapsTableModel downloadableMapsModel = new RemoteMapsTableModel(); private RemoteThemesTableModel downloadableThemesModel = new RemoteThemesTableModel(); private ItemModel<LocalMap> displayedMapModel = new ItemModel<LocalMap>(DISPLAYED_MAP_PREFERENCE, OPENSTREETMAP_URL) { protected LocalMap stringToItem(String url) { return getAvailableMapsModel().getMap(url); } protected String itemToString(LocalMap map) { return map.getUrl(); } }; private ItemModel<LocalTheme> appliedThemeModel = new ItemModel<LocalTheme>(APPLIED_THEME_PREFERENCE, OSMARENDER_URL) { protected LocalTheme stringToItem(String url) { return getAvailableThemesModel().getThemeByUrl(url); } protected String itemToString(LocalTheme theme) { return theme.getUrl(); } }; public MapManager(DataSourceManager dataSourceManager) { this.dataSourceManager = dataSourceManager; new ThemeForMapMediator(this); initializeOnlineMaps(); initializeBuiltinThemes(); } public LocalMapsTableModel getAvailableMapsModel() { return availableMapsModel; } public RemoteMapsTableModel getDownloadableMapsModel() { return downloadableMapsModel; } public ItemModel<LocalMap> getDisplayedMapModel() { return displayedMapModel; } public LocalThemesTableModel getAvailableThemesModel() { return availableThemesModel; } public RemoteThemesTableModel getDownloadableThemesModel() { return downloadableThemesModel; } public ItemModel<LocalTheme> getAppliedThemeModel() { return appliedThemeModel; } public File getMapsDirectory() { return new File(preferences.get(MAP_DIRECTORY_PREFERENCE, getApplicationDirectory("maps").getAbsolutePath())); } public File getThemesDirectory() { return new File(preferences.get(THEME_DIRECTORY_PREFERENCE, getApplicationDirectory("themes").getAbsolutePath())); } private void initializeOnlineMaps() { availableMapsModel.clear(); availableMapsModel.addOrUpdateMap(new OnlineMap("OpenStreetMap", OPENSTREETMAP_URL, OpenStreetMapMapnik.INSTANCE)); availableMapsModel.addOrUpdateMap(new OnlineMap("OpenCycleMap", "http://www.opencyclemap.org/", OpenCycleMap.INSTANCE)); } private void initializeBuiltinThemes() { availableThemesModel.clear(); availableThemesModel.addOrUpdateTheme(new VectorTheme("OpenStreetMap Osmarender", OSMARENDER_URL, OSMARENDER)); } public synchronized void scanMaps() throws IOException { initializeOnlineMaps(); long start = currentTimeMillis(); File mapsDirectory = ensureDirectory(getMapsDirectory()); List<File> mapFiles = collectFiles(mapsDirectory, ".map"); File[] mapFilesArray = mapFiles.toArray(new File[mapFiles.size()]); for (File file : mapFilesArray) { if(file.getParent().endsWith("routeconverter")) continue; availableMapsModel.addOrUpdateMap(new VectorMap(removePrefix(mapsDirectory, file), file.toURI().toString(), extractBoundingBox(file), file)); } long end = currentTimeMillis(); log.info(format("Collected %d map files %s from %s in %d milliseconds", mapFilesArray.length, printArrayToDialogString(mapFilesArray), mapsDirectory, (end - start))); } public synchronized void scanThemes() throws IOException { initializeBuiltinThemes(); long start = currentTimeMillis(); File themesDirectory = ensureDirectory(getThemesDirectory()); List<File> themeFiles = collectFiles(themesDirectory, ".xml"); File[] themeFilesArray = themeFiles.toArray(new File[themeFiles.size()]); for (File file : themeFilesArray) availableThemesModel.addOrUpdateTheme(new VectorTheme(removePrefix(themesDirectory, file), file.toURI().toString(), new ExternalRenderTheme(file))); long end = currentTimeMillis(); log.info(format("Collected %d theme files %s from %s in %d milliseconds", themeFilesArray.length, printArrayToDialogString(themeFilesArray), themesDirectory, (end - start))); } public void scanDatasources() { MapFilesService mapFilesService = new MapFilesService(dataSourceManager); mapFilesService.initialize(); List<RemoteMap> maps = mapFilesService.getMaps(); RemoteMap[] remoteMaps = maps.toArray(new RemoteMap[maps.size()]); sort(remoteMaps, new Comparator<RemoteResource>() { public int compare(RemoteResource r1, RemoteResource r2) { return (r1.getDataSource() + r1.getUrl()).compareToIgnoreCase(r2.getDataSource() + r2.getUrl()); } }); for (RemoteMap remoteMap : remoteMaps) downloadableMapsModel.addOrUpdateMap(remoteMap); List<RemoteTheme> themes = mapFilesService.getThemes(); RemoteTheme[] remoteThemes = themes.toArray(new RemoteTheme[themes.size()]); sort(remoteThemes, new Comparator<RemoteResource>() { public int compare(RemoteResource r1, RemoteResource r2) { return (r1.getDataSource() + r1.getUrl()).compareToIgnoreCase(r2.getDataSource() + r2.getUrl()); } }); for (RemoteTheme remoteTheme : remoteThemes) downloadableThemesModel.addOrUpdateTheme(remoteTheme); } public void queueForDownload(List<? extends RemoteResource> resources) { List<Download> downloads = new ArrayList<>(); for (RemoteResource resource : resources) { Downloadable downloadable = resource.getDownloadable(); DataSource dataSource = resource.getDataSource(); downloads.add(dataSourceManager.queueForDownload(dataSource, downloadable)); } dataSourceManager.getDownloadManager().waitForCompletion(downloads); } }