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, "power",        tr("Power"),               tr("Checks for errors on power infrastructures"));
154            addDefault(def, "religion",     tr("Religion"),            tr("Checks for errors on religious objects"));
155            addDefault(def, "relation",     tr("Relations"),           tr("Checks for errors on relations"));
156            addDefault(def, "unnecessary",  tr("Unnecessary tags"),    tr("Checks for unnecessary tags"));
157            addDefault(def, "wikipedia",    tr("Wikipedia"),           tr("Checks for wrong wikipedia tags"));
158
159            return def;
160        }
161
162        private static void addDefault(List<ExtendedSourceEntry> defaults, String filename, String title, String description) {
163            ExtendedSourceEntry i = new ExtendedSourceEntry(filename+".mapcss", "resource://data/validator/"+filename+".mapcss");
164            i.title = title;
165            i.description = description;
166            defaults.add(i);
167        }
168
169        @Override
170        public Map<String, String> serialize(SourceEntry entry) {
171            Map<String, String> res = new HashMap<>();
172            res.put("url", entry.url);
173            res.put("title", entry.title == null ? "" : entry.title);
174            res.put("active", Boolean.toString(entry.active));
175            return res;
176        }
177
178        @Override
179        public SourceEntry deserialize(Map<String, String> s) {
180            return new SourceEntry(s.get("url"), null, s.get("title"), Boolean.parseBoolean(s.get("active")));
181        }
182    }
183
184    private SourceEditor sources;
185
186    @Override
187    public void addGui(PreferenceTabbedPane gui) {
188        final ValidatorPreference valPref = gui.getValidatorPreference();
189        sources = new TagCheckerRulesSourceEditor();
190
191        valPref.addSubTab(this, tr("Tag checker rules"),
192                sources, tr("Choose Tag checker rules to enable"));
193        sources.deferLoading(valPref, sources);
194    }
195
196    @Override
197    public boolean ok() {
198        if (sources.finish()) {
199            // Reload sources
200            MapCSSTagChecker tagChecker = OsmValidator.getTest(MapCSSTagChecker.class);
201            if (tagChecker != null) {
202                OsmValidator.initializeTests(Collections.singleton(tagChecker));
203            }
204        }
205
206        return false;
207    }
208
209    @Override
210    public boolean isExpert() {
211        return false;
212    }
213
214    @Override
215    public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
216        return gui.getValidatorPreference();
217    }
218}