// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.opendata;
import java.awt.Image;
import java.io.File;
import java.net.URL;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.ImageIcon;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.ExtensionFileFilter;
import org.openstreetmap.josm.gui.MainMenu;
import org.openstreetmap.josm.gui.MapFrame;
import org.openstreetmap.josm.gui.MenuScroller;
import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.plugins.Plugin;
import org.openstreetmap.josm.plugins.PluginInformation;
import org.openstreetmap.josm.plugins.opendata.core.actions.DownloadDataAction;
import org.openstreetmap.josm.plugins.opendata.core.actions.DownloadDataTask;
import org.openstreetmap.josm.plugins.opendata.core.actions.OpenPreferencesActions;
import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
import org.openstreetmap.josm.plugins.opendata.core.datasets.DataSetCategory;
import org.openstreetmap.josm.plugins.opendata.core.gui.OdDialog;
import org.openstreetmap.josm.plugins.opendata.core.gui.OdPreferenceSetting;
import org.openstreetmap.josm.plugins.opendata.core.io.AbstractImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.XmlImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.archive.SevenZipImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.archive.ZipImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.GmlImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmlKmzImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.MifTabImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.geographic.ShpImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.CsvImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.OdsImporter;
import org.openstreetmap.josm.plugins.opendata.core.io.tabular.XlsImporter;
import org.openstreetmap.josm.plugins.opendata.core.modules.Module;
import org.openstreetmap.josm.plugins.opendata.core.modules.ModuleHandler;
import org.openstreetmap.josm.plugins.opendata.core.modules.ModuleInformation;
import org.openstreetmap.josm.plugins.opendata.core.util.OdUtils;
import org.openstreetmap.josm.tools.Pair;
public final class OdPlugin extends Plugin {
private static OdPlugin instance;
public final XmlImporter xmlImporter = new XmlImporter();
private final JMenu menu;
private OdDialog dialog;
public OdPlugin(PluginInformation info) {
super(info);
if (instance == null) {
instance = this;
} else {
throw new IllegalAccessError("Cannot instantiate plugin twice !");
}
// Allow JOSM to import more files
for (AbstractImporter importer : Arrays.asList(new AbstractImporter[]{
new CsvImporter(), new OdsImporter(), new XlsImporter(), // Tabular file formats
new KmlKmzImporter(), new ShpImporter(), new MifTabImporter(), new GmlImporter(), // Geographic file formats
new ZipImporter(), // Zip archive containing any of the others
new SevenZipImporter(), // 7Zip archive containing any of the others
xmlImporter // Generic importer for XML files (currently used for Neptune files)
})) {
ExtensionFileFilter.addImporterFirst(importer);
}
menu = Main.main.menu.dataMenu;
new Thread(new Runnable() {
@Override
public void run() {
// Load modules in new thread
loadModules();
// Add menu in EDT
GuiHelper.runInEDT(new Runnable() {
@Override
public void run() {
buildMenu();
}
});
}
}).start();
// Add download task
Main.main.menu.openLocation.addDownloadTaskClass(DownloadDataTask.class);
// Delete previous temp dirs if any (old plugin versions did not remove them correctly)
OdUtils.deletePreviousTempDirs();
}
public static OdPlugin getInstance() {
return instance;
}
private JMenu getModuleMenu(Module module) {
String moduleName = module.getDisplayedName();
if (moduleName == null || moduleName.isEmpty()) {
moduleName = module.getModuleInformation().getName();
}
JMenu moduleMenu = new JMenu(moduleName);
moduleMenu.setIcon(module.getModuleInformation().getScaledIcon());
return moduleMenu;
}
private void buildMenu() {
for (Module module : ModuleHandler.moduleList) {
Map<DataSetCategory, JMenu> catMenus = new HashMap<>();
JMenu moduleMenu = null;
for (AbstractDataSetHandler handler: module.getNewlyInstanciatedHandlers()) {
URL dataURL = handler.getDataURL();
List<Pair<String, URL>> dataURLs = handler.getDataURLs();
if (dataURL != null || (dataURLs != null && !dataURLs.isEmpty())) {
if (moduleMenu == null) {
moduleMenu = getModuleMenu(module);
}
DataSetCategory cat = handler.getCategory();
JMenu endMenu = null;
if (cat != null) {
if ((endMenu = catMenus.get(cat)) == null) {
catMenus.put(cat, endMenu = new JMenu(cat.getName()));
setMenuItemIcon(cat.getIcon(), endMenu);
moduleMenu.add(endMenu);
}
}
if (endMenu == null) {
endMenu = moduleMenu;
}
String handlerName = handler.getName();
if (handlerName == null || handlerName.isEmpty()) {
handlerName = handler.getClass().getName();
}
JMenuItem handlerItem = null;
if (dataURL != null) {
handlerItem = endMenu.add(new DownloadDataAction(module, handlerName, dataURL));
} else if (dataURLs != null) {
JMenu handlerMenu = new JMenu(handlerName);
JMenuItem item = null;
for (Pair<String, URL> pair : dataURLs) {
if (pair != null && pair.a != null && pair.b != null) {
item = handlerMenu.add(new DownloadDataAction(module, pair.a, pair.b));
}
}
if (item != null) {
MenuScroller.setScrollerFor(handlerMenu);
handlerItem = endMenu.add(handlerMenu);
}
}
if (handlerItem != null) {
setMenuItemIcon(handler.getMenuIcon(), handlerItem);
}
}
}
if (moduleMenu != null) {
menu.add(moduleMenu);
}
}
menu.addSeparator();
MainMenu.add(menu, new OpenPreferencesActions());
}
private void setMenuItemIcon(ImageIcon icon, JMenuItem menuItem) {
if (icon != null) {
if (icon.getIconHeight() != 16 || icon.getIconWidth() != 16) {
icon = new ImageIcon(icon.getImage().getScaledInstance(16, 16, Image.SCALE_DEFAULT));
}
menuItem.setIcon(icon);
}
}
@Override
public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
if (newFrame != null) {
newFrame.addToggleDialog(dialog = new OdDialog());
} else {
dialog = null;
}
}
@Override
public PreferenceSetting getPreferenceSetting() {
return new OdPreferenceSetting();
}
private void loadModules() {
List<ModuleInformation> modulesToLoad = ModuleHandler.buildListOfModulesToLoad(Main.parent);
if (!modulesToLoad.isEmpty() && ModuleHandler.checkAndConfirmModuleUpdate(Main.parent)) {
modulesToLoad = ModuleHandler.updateModules(Main.parent, modulesToLoad, null);
}
ModuleHandler.installDownloadedModules(true);
ModuleHandler.loadModules(Main.parent, modulesToLoad, null);
}
private File getSubDirectory(String name) {
File dir = new File(getPluginDir()+File.separator+name);
if (!dir.exists()) {
dir.mkdirs();
}
return dir;
}
public File getModulesDirectory() {
return getSubDirectory("modules");
}
public File getResourcesDirectory() {
return getSubDirectory("resources");
}
public OdDialog getDialog() {
return dialog;
}
}