// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.opendata.core.gui;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.gui.util.ChangeNotifier;
import org.openstreetmap.josm.plugins.opendata.OdPlugin;
import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
import org.openstreetmap.josm.plugins.opendata.core.modules.ModuleException;
import org.openstreetmap.josm.plugins.opendata.core.modules.ModuleInformation;
public class ModulePreferencesModel extends ChangeNotifier {
private final ArrayList<ModuleInformation> availableModules = new ArrayList<>();
private final ArrayList<ModuleInformation> displayedModules = new ArrayList<>();
private final HashMap<ModuleInformation, Boolean> selectedModulesMap = new HashMap<>();
private Set<String> pendingDownloads = new HashSet<>();
private String filterExpression;
private final Set<String> currentActiveModules;
protected Collection<String> getModules(Collection<String> def) {
return Main.pref.getCollection(OdConstants.PREF_MODULES, def);
}
public ModulePreferencesModel() {
currentActiveModules = new HashSet<>();
currentActiveModules.addAll(getModules(currentActiveModules));
}
public void filterDisplayedModules(String filter) {
if (filter == null) {
displayedModules.clear();
displayedModules.addAll(availableModules);
this.filterExpression = null;
return;
}
displayedModules.clear();
for (ModuleInformation pi: availableModules) {
if (pi.matches(filter)) {
displayedModules.add(pi);
}
}
filterExpression = filter;
fireStateChanged();
}
public void setAvailableModules(Collection<ModuleInformation> available) {
availableModules.clear();
if (available != null) {
availableModules.addAll(available);
}
sort();
filterDisplayedModules(filterExpression);
Set<String> activeModules = new HashSet<>();
activeModules.addAll(getModules(activeModules));
for (ModuleInformation pi: availableModules) {
if (selectedModulesMap.get(pi) == null) {
if (activeModules.contains(pi.name)) {
selectedModulesMap.put(pi, true);
}
}
}
fireStateChanged();
}
protected void updateAvailableModule(ModuleInformation other) {
if (other == null) return;
ModuleInformation pi = getModuleInformation(other.name);
if (pi == null) {
availableModules.add(other);
return;
}
pi.updateFromModuleSite(other);
}
/**
* Updates the list of module information objects with new information from
* module update sites.
*
* @param fromModuleSite module information read from module update sites
*/
public void updateAvailableModules(Collection<ModuleInformation> fromModuleSite) {
for (ModuleInformation other: fromModuleSite) {
updateAvailableModule(other);
}
sort();
filterDisplayedModules(filterExpression);
Set<String> activeModules = new HashSet<>();
activeModules.addAll(getModules(activeModules));
for (ModuleInformation pi: availableModules) {
if (selectedModulesMap.get(pi) == null) {
if (activeModules.contains(pi.name)) {
selectedModulesMap.put(pi, true);
}
}
}
fireStateChanged();
}
/**
* Replies the list of selected module information objects
*
* @return the list of selected module information objects
*/
public List<ModuleInformation> getSelectedModules() {
List<ModuleInformation> ret = new LinkedList<>();
for (ModuleInformation pi: availableModules) {
if (selectedModulesMap.get(pi) == null) {
continue;
}
if (selectedModulesMap.get(pi)) {
ret.add(pi);
}
}
return ret;
}
/**
* Replies the list of selected module information objects
*
* @return the list of selected module information objects
*/
public Set<String> getSelectedModuleNames() {
Set<String> ret = new HashSet<>();
for (ModuleInformation pi: getSelectedModules()) {
ret.add(pi.name);
}
return ret;
}
/**
* Sorts the list of available modules
*/
protected void sort() {
Collections.sort(
availableModules,
new Comparator<ModuleInformation>() {
@Override
public int compare(ModuleInformation o1, ModuleInformation o2) {
String n1 = o1.getName() == null ? "" : o1.getName().toLowerCase();
String n2 = o2.getName() == null ? "" : o2.getName().toLowerCase();
return n1.compareTo(n2);
}
}
);
}
/**
* Replies the list of module informations to display
*
* @return the list of module informations to display
*/
public List<ModuleInformation> getDisplayedModules() {
return displayedModules;
}
/**
* Replies the list of modules waiting for update or download
*
* @return the list of modules waiting for update or download
*/
public List<ModuleInformation> getModulesScheduledForUpdateOrDownload() {
List<ModuleInformation> ret = new ArrayList<>();
for (String module: pendingDownloads) {
ModuleInformation pi = getModuleInformation(module);
if (pi == null) {
continue;
}
ret.add(pi);
}
return ret;
}
/**
* Sets whether the module is selected or not.
*
* @param name the name of the module
* @param selected true, if selected; false, otherwise
*/
public void setModuleSelected(String name, boolean selected) {
ModuleInformation pi = getModuleInformation(name);
if (pi != null) {
selectedModulesMap.put(pi, selected);
if (pi.isUpdateRequired()) {
pendingDownloads.add(pi.name);
}
}
if (!selected) {
pendingDownloads.remove(name);
}
}
/**
* Removes all the module in {@code modules} from the list of modules
* with a pending download
*
* @param modules the list of modules to clear for a pending download
*/
public void clearPendingModules(Collection<ModuleInformation> modules) {
if (modules == null || modules.isEmpty()) return;
for (ModuleInformation pi : modules) {
pendingDownloads.remove(pi.name);
}
}
/**
* Replies the module info with the name <code>name</code>. null, if no
* such module info exists.
*
* @param name the name. If null, replies null.
* @return the module info.
*/
public ModuleInformation getModuleInformation(String name) {
for (ModuleInformation pi: availableModules) {
if (pi.getName() != null && pi.getName().equals(name))
return pi;
}
return null;
}
/**
* Initializes the model from preferences
*/
/*public void initFromPreferences() {
Collection<String> enabledModules = getModules(null);
if (enabledModules == null) {
this.selectedModulesMap.clear();
return;
}
for (String name: enabledModules) {
ModuleInformation pi = getModuleInformation(name);
if (pi == null) {
continue;
}
setModuleSelected(name, true);
}
}*/
/**
* Replies true if the module with name <code>name</code> is currently
* selected in the module model
*
* @param name the module name
* @return true if the module is selected; false, otherwise
*/
public boolean isSelectedModule(String name) {
ModuleInformation pi = getModuleInformation(name);
if (pi == null) return false;
if (selectedModulesMap.get(pi) == null) return false;
return selectedModulesMap.get(pi);
}
/**
* Replies the set of modules which have been added by the user to
* the set of activated modules.
*
* @return the set of newly deactivated modules
*/
/*public List<ModuleInformation> getNewlyActivatedModules() {
List<ModuleInformation> ret = new LinkedList<ModuleInformation>();
for (Entry<ModuleInformation, Boolean> entry: selectedModulesMap.entrySet()) {
ModuleInformation pi = entry.getKey();
boolean selected = entry.getValue();
if (selected && ! currentActiveModules.contains(pi.name)) {
ret.add(pi);
}
}
return ret;
}*/
/**
* Replies the set of modules which have been removed by the user from
* the set of activated modules.
*
* @return the set of newly deactivated modules
*/
/*public List<ModuleInformation> getNewlyDeactivatedModules() {
List<ModuleInformation> ret = new LinkedList<ModuleInformation>();
for (ModuleInformation pi: availableModules) {
if (!currentActiveModules.contains(pi.name)) {
continue;
}
if (selectedModulesMap.get(pi) == null || ! selectedModulesMap.get(pi)) {
ret.add(pi);
}
}
return ret;
}*/
/**
* Replies the set of module names which have been added by the user to
* the set of activated modules.
*
* @return the set of newly activated module names
*/
/*public Set<String> getNewlyActivatedModuleNames() {
Set<String> ret = new HashSet<String>();
List<ModuleInformation> modules = getNewlyActivatedModules();
for (ModuleInformation pi: modules) {
ret.add(pi.name);
}
return ret;
}*/
/**
* Replies true if the set of active modules has been changed by the user
* in this preference model. He has either added modules or removed modules
* being active before.
*
* @return true if the collection of active modules has changed
*/
public boolean isActiveModulesChanged() {
Set<String> newActiveModules = getSelectedModuleNames();
return !newActiveModules.equals(currentActiveModules);
}
/**
* Refreshes the local version field on the modules in <code>modules</code> with
* the version in the manifest of the downloaded "jar.new"-file for this module.
*
* @param modules the collections of modules to refresh
*/
public void refreshLocalModuleVersion(Collection<ModuleInformation> modules) {
if (modules == null) return;
File moduleDir = OdPlugin.getInstance().getModulesDirectory();
for (ModuleInformation pi : modules) {
// Find the downloaded file. We have tried to install the downloaded modules
// (ModuleHandler.installDownloadedModules). This succeeds depending on the
// platform.
File downloadedModuleFile = new File(moduleDir, pi.name + ".jar.new");
if (!(downloadedModuleFile.exists() && downloadedModuleFile.canRead())) {
downloadedModuleFile = new File(moduleDir, pi.name + ".jar");
if (!(downloadedModuleFile.exists() && downloadedModuleFile.canRead())) {
continue;
}
}
try {
ModuleInformation newinfo = new ModuleInformation(downloadedModuleFile, pi.name);
ModuleInformation oldinfo = getModuleInformation(pi.name);
if (oldinfo == null) {
// should not happen
continue;
}
oldinfo.localversion = newinfo.version;
} catch (ModuleException e) {
e.printStackTrace();
}
}
}
}