001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.gui.preferences.validator; 003 004import static org.openstreetmap.josm.tools.I18n.marktr; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.util.ArrayList; 008import java.util.Collection; 009import java.util.Collections; 010import java.util.HashMap; 011import java.util.List; 012import java.util.Map; 013 014import org.openstreetmap.josm.Main; 015import org.openstreetmap.josm.data.validation.OsmValidator; 016import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker; 017import org.openstreetmap.josm.gui.preferences.PreferenceSetting; 018import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory; 019import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane; 020import org.openstreetmap.josm.gui.preferences.SourceEditor; 021import org.openstreetmap.josm.gui.preferences.SourceEditor.ExtendedSourceEntry; 022import org.openstreetmap.josm.gui.preferences.SourceEntry; 023import org.openstreetmap.josm.gui.preferences.SourceProvider; 024import org.openstreetmap.josm.gui.preferences.SourceType; 025import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting; 026import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting; 027import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference; 028 029/** 030 * The general validator preferences, allowing to enable/disable tests. 031 * @since 6669 032 */ 033public class ValidatorTagCheckerRulesPreference implements SubPreferenceSetting { 034 035 /** 036 * Factory used to create a new {@code ValidatorTagCheckerRulesPreference}. 037 */ 038 public static class Factory implements PreferenceSettingFactory { 039 @Override 040 public PreferenceSetting createPreferenceSetting() { 041 return new ValidatorTagCheckerRulesPreference(); 042 } 043 } 044 045 private static final List<SourceProvider> ruleSourceProviders = new ArrayList<>(); 046 047 /** 048 * Registers a new additional rule source provider. 049 * @param provider The rule source provider 050 * @return {@code true}, if the provider has been added, {@code false} otherwise 051 */ 052 public static final boolean registerSourceProvider(SourceProvider provider) { 053 if (provider != null) 054 return ruleSourceProviders.add(provider); 055 return false; 056 } 057 058 static class TagCheckerRulesSourceEditor extends SourceEditor { 059 060 TagCheckerRulesSourceEditor() { 061 super(SourceType.TAGCHECKER_RULE, Main.getJOSMWebsite()+"/rules", ruleSourceProviders, false); 062 } 063 064 @Override 065 public Collection<? extends SourceEntry> getInitialSourcesList() { 066 return RulePrefHelper.INSTANCE.get(); 067 } 068 069 @Override 070 public boolean finish() { 071 return RulePrefHelper.INSTANCE.put(activeSourcesModel.getSources()); 072 } 073 074 @Override 075 public Collection<ExtendedSourceEntry> getDefault() { 076 return RulePrefHelper.INSTANCE.getDefault(); 077 } 078 079 @Override 080 public Collection<String> getInitialIconPathsList() { 081 return null; 082 } 083 084 @Override 085 public String getStr(I18nString ident) { 086 switch (ident) { 087 case AVAILABLE_SOURCES: 088 return tr("Available rules:"); 089 case ACTIVE_SOURCES: 090 return tr("Active rules:"); 091 case NEW_SOURCE_ENTRY_TOOLTIP: 092 return tr("Add a new rule by entering filename or URL"); 093 case NEW_SOURCE_ENTRY: 094 return tr("New rule entry:"); 095 case REMOVE_SOURCE_TOOLTIP: 096 return tr("Remove the selected rules from the list of active rules"); 097 case EDIT_SOURCE_TOOLTIP: 098 return tr("Edit the filename or URL for the selected active rule"); 099 case ACTIVATE_TOOLTIP: 100 return tr("Add the selected available rules to the list of active rules"); 101 case RELOAD_ALL_AVAILABLE: 102 return marktr("Reloads the list of available rules from ''{0}''"); 103 case LOADING_SOURCES_FROM: 104 return marktr("Loading rule sources from ''{0}''"); 105 case FAILED_TO_LOAD_SOURCES_FROM: 106 return marktr("<html>Failed to load the list of rule sources from<br>" 107 + "''{0}''.<br>" 108 + "<br>" 109 + "Details (untranslated):<br>{1}</html>"); 110 case FAILED_TO_LOAD_SOURCES_FROM_HELP_TOPIC: 111 return "/Preferences/Rules#FailedToLoadRuleSources"; 112 case ILLEGAL_FORMAT_OF_ENTRY: 113 return marktr("Warning: illegal format of entry in rule list ''{0}''. Got ''{1}''"); 114 default: throw new AssertionError(); 115 } 116 } 117 118 @Override 119 protected String getTitleForSourceEntry(SourceEntry entry) { 120 final String title = MapPaintPreference.getTitleFromSourceEntry(entry); 121 return title != null ? title : super.getTitleForSourceEntry(entry); 122 } 123 } 124 125 /** 126 * Helper class for validator tag checker rules preferences. 127 */ 128 public static class RulePrefHelper extends SourceEditor.SourcePrefHelper { 129 130 /** 131 * The unique instance. 132 */ 133 public static final RulePrefHelper INSTANCE = new RulePrefHelper(); 134 135 /** 136 * Constructs a new {@code PresetPrefHelper}. 137 */ 138 public RulePrefHelper() { 139 super(MapCSSTagChecker.ENTRIES_PREF_KEY); 140 } 141 142 @Override 143 public Collection<ExtendedSourceEntry> getDefault() { 144 List<ExtendedSourceEntry> def = new ArrayList<>(); 145 146 addDefault(def, "addresses", tr("Addresses"), tr("Checks for errors on addresses")); 147 addDefault(def, "combinations", tr("Tag combinations"), tr("Checks for missing tag or suspicious combinations")); 148 addDefault(def, "deprecated", tr("Deprecated features"), tr("Checks for deprecated features")); 149 addDefault(def, "geometry", tr("Geometry"), tr("Checks for geometry errors")); 150 addDefault(def, "highway", tr("Highways"), tr("Checks for errors on highways")); 151 addDefault(def, "multiple", tr("Multiple values"), tr("Checks for wrong multiple values")); 152 addDefault(def, "numeric", tr("Numeric values"), tr("Checks for wrong numeric values")); 153 addDefault(def, "religion", tr("Religion"), tr("Checks for errors on religious objects")); 154 addDefault(def, "relation", tr("Relations"), tr("Checks for errors on relations")); 155 addDefault(def, "unnecessary", tr("Unnecessary tags"), tr("Checks for unnecessary tags")); 156 addDefault(def, "wikipedia", tr("Wikipedia"), tr("Checks for wrong wikipedia tags")); 157 158 return def; 159 } 160 161 private static void addDefault(List<ExtendedSourceEntry> defaults, String filename, String title, String description) { 162 ExtendedSourceEntry i = new ExtendedSourceEntry(filename+".mapcss", "resource://data/validator/"+filename+".mapcss"); 163 i.title = title; 164 i.description = description; 165 defaults.add(i); 166 } 167 168 @Override 169 public Map<String, String> serialize(SourceEntry entry) { 170 Map<String, String> res = new HashMap<>(); 171 res.put("url", entry.url); 172 res.put("title", entry.title == null ? "" : entry.title); 173 res.put("active", Boolean.toString(entry.active)); 174 return res; 175 } 176 177 @Override 178 public SourceEntry deserialize(Map<String, String> s) { 179 return new SourceEntry(s.get("url"), null, s.get("title"), Boolean.parseBoolean(s.get("active"))); 180 } 181 } 182 183 private SourceEditor sources; 184 185 @Override 186 public void addGui(PreferenceTabbedPane gui) { 187 final ValidatorPreference valPref = gui.getValidatorPreference(); 188 sources = new TagCheckerRulesSourceEditor(); 189 190 valPref.addSubTab(this, tr("Tag checker rules"), 191 sources, tr("Choose Tag checker rules to enable")); 192 sources.deferLoading(valPref, sources); 193 } 194 195 @Override 196 public boolean ok() { 197 if (sources.finish()) { 198 // Reload sources 199 MapCSSTagChecker tagChecker = OsmValidator.getTest(MapCSSTagChecker.class); 200 if (tagChecker != null) { 201 OsmValidator.initializeTests(Collections.singleton(tagChecker)); 202 } 203 } 204 205 return false; 206 } 207 208 @Override 209 public boolean isExpert() { 210 return false; 211 } 212 213 @Override 214 public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) { 215 return gui.getValidatorPreference(); 216 } 217}