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