Changeset 18918 in josm for trunk/src/org


Ignore:
Timestamp:
2023-12-19T17:09:19+01:00 (11 months ago)
Author:
taylor.smock
Message:

Fix #23290: Validate the regions a tag is expected to be in (patch by Sarabjeet108, modified)

Modifications are as follows:

  • Allow the use of the new region attributes for keys inside a preset
  • Basic tests

regions comes from Vespucci's extensions: https://vespucci.io/tutorials/presets/#extensions

Location:
trunk/src/org/openstreetmap/josm
Files:
1 added
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/osm/OsmUtils.java

    r18801 r18918  
    3636    /**
    3737     * Discouraged synonym for {@link #TRUE_VALUE}
    38      * @deprecated since xxx, use {@link #TRUE_VALUE} instead.
     38     * @deprecated since 18801, use {@link #TRUE_VALUE} instead.
    3939     */
    4040    @Deprecated
     
    4242    /**
    4343     * Discouraged synonym for {@link #FALSE_VALUE}
    44      * @deprecated since xxx, use {@link #FALSE_VALUE} instead.
     44     * @deprecated since 18801, use {@link #FALSE_VALUE} instead.
    4545     */
    4646    @Deprecated
     
    4848    /**
    4949     * Discouraged synonym for {@link #REVERSE_VALUE}
    50      * @deprecated since xxx, use {@link #REVERSE_VALUE} instead.
     50     * @deprecated since 18801, use {@link #REVERSE_VALUE} instead.
    5151     */
    5252    @Deprecated
  • trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java

    r18900 r18918  
    2525import java.util.Map;
    2626import java.util.Map.Entry;
     27import java.util.Objects;
    2728import java.util.OptionalInt;
    2829import java.util.Set;
     
    3839import org.openstreetmap.josm.command.Command;
    3940import org.openstreetmap.josm.command.SequenceCommand;
     41import org.openstreetmap.josm.data.coor.LatLon;
    4042import org.openstreetmap.josm.data.osm.AbstractPrimitive;
    4143import org.openstreetmap.josm.data.osm.DataSet;
     44import org.openstreetmap.josm.data.osm.Node;
    4245import org.openstreetmap.josm.data.osm.OsmPrimitive;
    4346import org.openstreetmap.josm.data.osm.OsmUtils;
     
    6366import org.openstreetmap.josm.gui.tagging.presets.items.Check;
    6467import org.openstreetmap.josm.gui.tagging.presets.items.CheckGroup;
     68import org.openstreetmap.josm.gui.tagging.presets.items.ComboMultiSelect;
     69import org.openstreetmap.josm.gui.tagging.presets.items.Key;
    6570import org.openstreetmap.josm.gui.tagging.presets.items.KeyedItem;
     71import org.openstreetmap.josm.gui.tagging.presets.items.PresetListEntry;
     72import org.openstreetmap.josm.gui.tagging.presets.items.RegionSpecific;
    6673import org.openstreetmap.josm.gui.widgets.EditableList;
    6774import org.openstreetmap.josm.io.CachedFile;
    6875import org.openstreetmap.josm.spi.preferences.Config;
    6976import org.openstreetmap.josm.tools.GBC;
     77import org.openstreetmap.josm.tools.JosmRuntimeException;
    7078import org.openstreetmap.josm.tools.Logging;
    7179import org.openstreetmap.josm.tools.MultiMap;
     80import org.openstreetmap.josm.tools.Territories;
    7281import org.openstreetmap.josm.tools.Utils;
    7382
     
    132141     */
    133142    public static final String PREF_CHECK_PRESETS_TYPES = PREFIX + ".checkPresetsTypes";
     143    public static final String PREF_CHECK_REGIONS = PREFIX + ".checkPresetsRegions";
    134144
    135145    /**
     
    160170     */
    161171    public static final String PREF_CHECK_PRESETS_TYPES_BEFORE_UPLOAD = PREF_CHECK_PRESETS_TYPES + BEFORE_UPLOAD;
     172    public static final String PREF_CHECK_REGIONS_BEFORE_UPLOAD = PREF_CHECK_REGIONS + BEFORE_UPLOAD;
    162173
    163174    /**
     
    176187    protected boolean checkFixmes;
    177188    protected boolean checkPresetsTypes;
     189    protected boolean checkRegions;
    178190
    179191    protected JCheckBox prefCheckKeys;
     
    182194    protected JCheckBox prefCheckFixmes;
    183195    protected JCheckBox prefCheckPresetsTypes;
     196    protected JCheckBox prefCheckRegions;
    184197
    185198    protected JCheckBox prefCheckKeysBeforeUpload;
     
    188201    protected JCheckBox prefCheckFixmesBeforeUpload;
    189202    protected JCheckBox prefCheckPresetsTypesBeforeUpload;
     203    protected JCheckBox prefCheckRegionsBeforeUpload;
    190204
    191205    // CHECKSTYLE.OFF: SingleSpaceSeparator
     
    211225    protected static final int MULTIPOLYGON_MAYBE_NO_AREA       = 1220;
    212226    protected static final int MULTIPOLYGON_SAME_TAG_ON_OUTER   = 1221;
     227    protected static final int INVALID_REGION                   = 1222;
    213228    // CHECKSTYLE.ON: SingleSpaceSeparator
    214229
     
    560575     * @return {@code true} if the given key is in internal presets
    561576     * @since 9023
    562      * @deprecated Use {@link TaggingPresets#isKeyInPresets(String)} instead
     577     * @deprecated since 18281 -- use {@link TaggingPresets#isKeyInPresets(String)} instead
    563578     */
    564579    @Deprecated
     
    653668
    654669        if (p instanceof Relation && p.hasTag("type", "multipolygon")) {
    655         checkMultipolygonTags(p);
    656         }
    657 
    658         if (checkPresetsTypes) {
    659             TagMap tags = p.getKeys();
    660             TaggingPresetType presetType = TaggingPresetType.forPrimitive(p);
    661             EnumSet<TaggingPresetType> presetTypes = EnumSet.of(presetType);
    662 
    663             Collection<TaggingPreset> matchingPresets = presetIndex.entrySet().stream()
     670            checkMultipolygonTags(p);
     671        }
     672
     673        final Collection<TaggingPreset> matchingPresets;
     674        TagMap tags;
     675        if (checkPresetsTypes || checkRegions) {
     676            tags = p.getKeys();
     677            matchingPresets = presetIndex.entrySet().stream()
    664678                    .filter(e -> TaggingPresetItem.matches(e.getValue(), tags))
    665679                    .map(Entry::getKey)
    666680                    .collect(Collectors.toCollection(LinkedHashSet::new));
    667             Collection<TaggingPreset> matchingPresetsOK = matchingPresets.stream().filter(
    668                     tp -> tp.typeMatches(presetTypes)).collect(Collectors.toList());
    669             Collection<TaggingPreset> matchingPresetsKO = matchingPresets.stream().filter(
    670                     tp -> !tp.typeMatches(presetTypes)).collect(Collectors.toList());
    671 
    672             for (TaggingPreset tp : matchingPresetsKO) {
    673                 // Potential error, unless matching tags are all known by a supported preset
    674                 Map<String, String> matchingTags = tp.data.stream()
     681        } else {
     682            matchingPresets = null;
     683            tags = null;
     684        }
     685
     686        if (checkPresetsTypes) {
     687            checkPresetsTypes(p, matchingPresets, tags);
     688        }
     689
     690        if (checkRegions) {
     691            checkRegions(p, matchingPresets);
     692        }
     693    }
     694
     695    /**
     696     * Check that the primitive matches the preset types for the preset
     697     * @param p The primitive to check
     698     * @param matchingPresets The presets to go through
     699     * @param tags Tags from the primitive to check
     700     */
     701    private void checkPresetsTypes(OsmPrimitive p, Collection<TaggingPreset> matchingPresets, Map<String, String> tags) {
     702        TaggingPresetType presetType = TaggingPresetType.forPrimitive(p);
     703        EnumSet<TaggingPresetType> presetTypes = EnumSet.of(presetType);
     704
     705        Collection<TaggingPreset> matchingPresetsOK = matchingPresets.stream().filter(
     706                tp -> tp.typeMatches(presetTypes)).collect(Collectors.toList());
     707        Collection<TaggingPreset> matchingPresetsKO = matchingPresets.stream().filter(
     708                tp -> !tp.typeMatches(presetTypes)).collect(Collectors.toList());
     709
     710        for (TaggingPreset tp : matchingPresetsKO) {
     711            // Potential error, unless matching tags are all known by a supported preset
     712            Map<String, String> matchingTags = tp.data.stream()
    675713                    .filter(i -> Boolean.TRUE.equals(i.matches(tags)))
    676714                    .filter(i -> i instanceof KeyedItem).map(i -> ((KeyedItem) i).key)
    677715                    .collect(Collectors.toMap(k -> k, tags::get));
    678                 if (matchingPresetsOK.stream().noneMatch(
    679                         tp2 -> matchingTags.entrySet().stream().allMatch(
    680                                 e -> tp2.data.stream().anyMatch(
    681                                         i -> i instanceof KeyedItem && ((KeyedItem) i).key.equals(e.getKey()))))) {
    682                     errors.add(TestError.builder(this, Severity.OTHER, INVALID_PRESETS_TYPE)
    683                             .message(tr("Object type not in preset"),
    684                                     marktr("Object type {0} is not supported by tagging preset: {1}"),
    685                                     tr(presetType.getName()), tp.getLocaleName())
     716            if (matchingPresetsOK.stream().noneMatch(
     717                    tp2 -> matchingTags.entrySet().stream().allMatch(
     718                            e -> tp2.data.stream().anyMatch(
     719                                    i -> i instanceof KeyedItem && ((KeyedItem) i).key.equals(e.getKey()))))) {
     720                errors.add(TestError.builder(this, Severity.OTHER, INVALID_PRESETS_TYPE)
     721                        .message(tr("Object type not in preset"),
     722                                marktr("Object type {0} is not supported by tagging preset: {1}"),
     723                                tr(presetType.getName()), tp.getLocaleName())
     724                        .primitives(p)
     725                        .build());
     726            }
     727        }
     728    }
     729
     730    /**
     731     * Check that the preset is valid for the region the primitive is in
     732     * @param p The primitive to check
     733     * @param matchingPresets The presets to check against
     734     */
     735    private void checkRegions(OsmPrimitive p, Collection<TaggingPreset> matchingPresets) {
     736        LatLon center;
     737        if (p instanceof Node) {
     738            center = ((Node) p).getCoor();
     739        } else {
     740            center = p.getBBox().getCenter();
     741        }
     742        for (TaggingPreset preset : matchingPresets) {
     743            if (preset.regions() != null) {
     744                boolean isInRegion = false; //true if the object is in an applicable region
     745                for (String region : preset.regions()) {
     746                    if (Territories.isIso3166Code(region, center)) { //check if center of the object is in a region
     747                        isInRegion = true;
     748                    }
     749                }
     750                if (isInRegion == preset.exclude_regions()) {
     751                    errors.add(TestError.builder(this, Severity.WARNING, INVALID_REGION)
     752                            .message(tr("Invalid region for this preset"),
     753                                    marktr("Preset {0} should not be applied in this region"),
     754                                    preset.getLocaleName())
    686755                            .primitives(p)
    687756                            .build());
    688757                }
    689758            }
    690         }
     759            // Check the tags
     760            tagCheck(preset, p, center, preset.data);
     761        }
     762    }
     763
     764    /**
     765     * Perform the checks against a given preset value
     766     * @param preset The originating preset (used for error creation)
     767     * @param p The originating primitive (used for error creation)
     768     * @param center The center of the primitive or other location of the primitive to check
     769     * @param tagInformation The sub items for the preset
     770     */
     771    private void tagCheck(TaggingPreset preset, OsmPrimitive p, LatLon center, List<? extends TaggingPresetItem> tagInformation) {
     772        for (TaggingPresetItem item : tagInformation) {
     773            if (item instanceof CheckGroup) {
     774                tagCheckReal(preset, p, center, ((CheckGroup) item).checks);
     775            } else if (item instanceof ComboMultiSelect) {
     776                tagCheckReal(preset, p, center, ((ComboMultiSelect) item).presetListEntries());
     777            }
     778            if (item instanceof RegionSpecific && ((RegionSpecific) item).regions() != null) {
     779                tagCheckReal(preset, p, center, (RegionSpecific) item);
     780            }
     781        }
     782    }
     783
     784    /**
     785     * Perform the checks against a given preset value
     786     * @param preset The originating preset (used for error creation)
     787     * @param p The originating primitive (used for error creation)
     788     * @param center The center of the primitive or other location of the primitive to check
     789     * @param data The data for the region specific information
     790     */
     791    private void tagCheckReal(TaggingPreset preset, OsmPrimitive p, LatLon center, List<? extends RegionSpecific> data) {
     792        for (RegionSpecific regionSpecific : data) {
     793            if (regionSpecific.regions() != null) {
     794                tagCheckReal(preset, p, center, regionSpecific);
     795            }
     796        }
     797    }
     798
     799    /**
     800     * Perform the checks against a given preset value
     801     * @param preset The originating preset (used for error creation)
     802     * @param p The originating primitive (used for error creation)
     803     * @param center The center of the primitive or other location of the primitive to check
     804     * @param data The data for the region specific information
     805     */
     806    private void tagCheckReal(TaggingPreset preset, OsmPrimitive p, LatLon center, RegionSpecific data) {
     807        // First, check if we aren't in the region for the tag
     808        if (latLonInRegions(center, data.regions()) == data.exclude_regions()) {
     809            final String key;
     810            final String value;
     811            if (data instanceof PresetListEntry) {
     812                key = ((PresetListEntry) data).cms.key;
     813                value = ((PresetListEntry) data).value;
     814            } else if (data instanceof KeyedItem) {
     815                key = ((KeyedItem) data).key;
     816                if (data instanceof Key) {
     817                    value = ((Key) data).value;
     818                } else {
     819                    value = null;
     820                }
     821            } else {
     822                throw new JosmRuntimeException("Unknown implementor for RegionSpecific");
     823            }
     824            if (p.hasTag(key) && (value == null || value.equals(p.get(key)))) {
     825                final TestError.Builder builder = TestError.builder(this, Severity.WARNING, INVALID_REGION)
     826                        .primitives(p);
     827                if (value == null) {
     828                    builder.message(tr("Invalid region for this preset"),
     829                            marktr("Preset {0} should not have the key {1}"),
     830                            preset.getLocaleName(), key);
     831                } else {
     832                    builder.message(tr("Invalid region for this preset"),
     833                            marktr("Preset {0} should not have the tag {1}={2}"),
     834                            preset.getLocaleName(), key, value);
     835                }
     836                errors.add(builder.build());
     837            }
     838        }
     839    }
     840
     841    /**
     842     * Check if the specified latlon is inside any of the specified regions
     843     * @param latLon The {@link LatLon} to check
     844     * @param regions The regions to see if the {@link LatLon} is in
     845     * @return {@code true} if the coordinate is inside any of the regions
     846     */
     847    private static boolean latLonInRegions(LatLon latLon, Collection<String> regions) {
     848        if (regions != null) {
     849            for (String region : regions) {
     850                if (Territories.isIso3166Code(region, latLon)) {
     851                    return true;
     852                }
     853            }
     854        }
     855        return false;
    691856    }
    692857
     
    9161081        }
    9171082
    918         if (!Utils.isEmpty(fixedKey) && !fixedKey.equals(key)) {
     1083        if (!Utils.isEmpty(fixedKey) && !Objects.equals(fixedKey, key)) {
    9191084            final String proposedKey = fixedKey;
    9201085            // misspelled preset key
     
    11011266            checkPresetsTypes = checkPresetsTypes && Config.getPref().getBoolean(PREF_CHECK_PRESETS_TYPES_BEFORE_UPLOAD, true);
    11021267        }
     1268
     1269        checkRegions = includeOtherSeverity && Config.getPref().getBoolean(PREF_CHECK_REGIONS, true);
     1270        if (isBeforeUpload) {
     1271            checkRegions = checkRegions && Config.getPref().getBoolean(PREF_CHECK_REGIONS_BEFORE_UPLOAD, true);
     1272        }
    11031273        deprecatedChecker = OsmValidator.getTest(MapCSSTagChecker.class);
    11041274        ignoreForOuterMPSameTagCheck.addAll(Config.getPref().getList(PREF_KEYS_IGNORE_OUTER_MP_SAME_TAG, Collections.emptyList()));
     
    11131283    @Override
    11141284    public void visit(Collection<OsmPrimitive> selection) {
    1115         if (checkKeys || checkValues || checkComplex || checkFixmes || checkPresetsTypes) {
     1285        if (checkKeys || checkValues || checkComplex || checkFixmes || checkPresetsTypes || checkRegions) {
    11161286            super.visit(selection);
    11171287        }
     
    11781348        prefCheckPresetsTypesBeforeUpload.setSelected(Config.getPref().getBoolean(PREF_CHECK_PRESETS_TYPES_BEFORE_UPLOAD, true));
    11791349        testPanel.add(prefCheckPresetsTypesBeforeUpload, a);
     1350
     1351        prefCheckRegions = new JCheckBox(tr("Check for regions."), Config.getPref().getBoolean(PREF_CHECK_REGIONS, true));
     1352        prefCheckRegions.setToolTipText(tr("Validate that objects are in the correct region."));
     1353        testPanel.add(prefCheckRegions, GBC.std().insets(20, 0, 0, 0));
     1354
     1355        prefCheckRegionsBeforeUpload = new JCheckBox();
     1356        prefCheckRegionsBeforeUpload.setSelected(Config.getPref().getBoolean(PREF_CHECK_REGIONS_BEFORE_UPLOAD, true));
     1357        testPanel.add(prefCheckRegionsBeforeUpload, a);
    11801358    }
    11811359
     
    12001378        Config.getPref().putBoolean(PREF_CHECK_FIXMES, prefCheckFixmes.isSelected());
    12011379        Config.getPref().putBoolean(PREF_CHECK_PRESETS_TYPES, prefCheckPresetsTypes.isSelected());
     1380        Config.getPref().putBoolean(PREF_CHECK_REGIONS, prefCheckRegions.isSelected());
    12021381        Config.getPref().putBoolean(PREF_CHECK_VALUES_BEFORE_UPLOAD, prefCheckValuesBeforeUpload.isSelected());
    12031382        Config.getPref().putBoolean(PREF_CHECK_COMPLEX_BEFORE_UPLOAD, prefCheckComplexBeforeUpload.isSelected());
     
    12051384        Config.getPref().putBoolean(PREF_CHECK_FIXMES_BEFORE_UPLOAD, prefCheckFixmesBeforeUpload.isSelected());
    12061385        Config.getPref().putBoolean(PREF_CHECK_PRESETS_TYPES_BEFORE_UPLOAD, prefCheckPresetsTypesBeforeUpload.isSelected());
     1386        Config.getPref().putBoolean(PREF_CHECK_REGIONS_BEFORE_UPLOAD, prefCheckRegionsBeforeUpload.isSelected());
    12071387        return Config.getPref().putList(PREF_SOURCES, sourcesList.getItems());
    12081388    }
  • trunk/src/org/openstreetmap/josm/gui/NoteInputDialog.java

    r18839 r18918  
    5353     * @param icon Icon to display in the action button
    5454     * @param text Default text of the note's comment
    55      * @since xxx
     55     * @since 18839
    5656     */
    5757    public void showNoteDialog(String message, Icon icon, String text) {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/Environment.java

    r18757 r18918  
    285285     * @param selector The selector to use
    286286     * @return A clone of this environment, with the specified selector
    287      * @since xxx
     287     * @since 18757
    288288     */
    289289    public Environment withSelector(Selector selector) {
     
    335335     * Get the selector for this environment
    336336     * @return The selector. May be {@code null}.
    337      * @since xxx
     337     * @since 18757
    338338     */
    339339    public Selector selector() {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/PlaceholderExpression.java

    r18758 r18918  
    1515/**
    1616 * Used for expressions that contain placeholders
    17  * @since xxx
     17 * @since 18758
    1818 */
    1919public final class PlaceholderExpression implements Expression {
  • trunk/src/org/openstreetmap/josm/gui/oauth/TestAccessTokenTask.java

    r18764 r18918  
    8080     * @param parameters the OAuth parameters. Must not be null.
    8181     * @param accessToken the Access Token. Must not be null.
    82      * @since xxx
     82     * @since 18764
    8383     */
    8484    public TestAccessTokenTask(Component parent, String apiUrl, IOAuthParameters parameters, IOAuthToken accessToken) {
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPreset.java

    r18866 r18918  
    6868import org.openstreetmap.josm.gui.tagging.presets.items.Roles;
    6969import org.openstreetmap.josm.gui.tagging.presets.items.Space;
     70import org.openstreetmap.josm.gui.tagging.presets.items.RegionSpecific;
    7071import org.openstreetmap.josm.gui.util.GuiHelper;
    7172import org.openstreetmap.josm.tools.GBC;
     
    8990 * @since 294
    9091 */
    91 public class TaggingPreset extends AbstractAction implements ActiveLayerChangeListener, AdaptableAction, Predicate<IPrimitive> {
     92public class TaggingPreset extends AbstractAction implements ActiveLayerChangeListener, AdaptableAction, Predicate<IPrimitive>,
     93        RegionSpecific {
    9294
    9395    /** The user pressed the "Apply" button */
     
    142144     */
    143145    public transient Set<TaggingPresetType> types;
     146    /**
     147     * List of regions the preset is applicable for.
     148     */
     149    private Collection<String> regions;
     150    /**
     151     * If true, invert the meaning of regions.
     152     */
     153    private boolean excludeRegions;
    144154    /**
    145155     * The list of preset items
     
    350360    }
    351361
     362    @Override
     363    public final Collection<String> regions() {
     364        return this.regions != null || this.group == null ? this.regions : this.group.regions();
     365    }
     366
     367    @Override
     368    public final void realSetRegions(Collection<String> regions) {
     369        this.regions = regions;
     370    }
     371
     372    @Override
     373    public final boolean exclude_regions() {
     374        return this.excludeRegions;
     375    }
     376
     377    @Override
     378    public final void setExclude_regions(boolean excludeRegions) {
     379        this.excludeRegions = excludeRegions;
     380    }
     381
    352382    private static class PresetPanel extends JPanel {
    353383        private boolean hasElements;
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetValidation.java

    r18001 r18918  
    2525import org.openstreetmap.josm.data.validation.tests.MapCSSTagChecker;
    2626import org.openstreetmap.josm.data.validation.tests.OpeningHourTest;
     27import org.openstreetmap.josm.data.validation.tests.TagChecker;
    2728import org.openstreetmap.josm.gui.MainApplication;
     29import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
    2830import org.openstreetmap.josm.gui.util.GuiHelper;
    2931import org.openstreetmap.josm.tools.Logging;
     
    5658            MapCSSTagChecker mapCSSTagChecker = OsmValidator.getTest(MapCSSTagChecker.class);
    5759            OpeningHourTest openingHourTest = OsmValidator.getTest(OpeningHourTest.class);
    58             OsmValidator.initializeTests(Arrays.asList(mapCSSTagChecker, openingHourTest));
     60            TagChecker tagChecker = OsmValidator.getTest(TagChecker.class);
     61            tagChecker.startTest(NullProgressMonitor.INSTANCE); //since initializeTest works if test is enabled
     62            OsmValidator.initializeTests(Arrays.asList(mapCSSTagChecker, openingHourTest, tagChecker));
     63
    5964
    6065            List<TestError> errors = new ArrayList<>();
    6166            openingHourTest.addErrorsForPrimitive(primitive, errors);
    6267            errors.addAll(mapCSSTagChecker.getErrorsForPrimitive(primitive, ValidatorPrefHelper.PREF_OTHER.get()));
     68            tagChecker.check(primitive);
     69            errors.addAll(tagChecker.getErrors());
    6370
    6471            boolean visible = !errors.isEmpty();
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/ComboMultiSelect.java

    r18801 r18918  
    1111import java.util.Arrays;
    1212import java.util.Collection;
     13import java.util.Collections;
    1314import java.util.List;
    1415import java.util.Map;
     
    310311        }
    311312
    312         if (values_sort && TaggingPresets.SORT_MENU.get()) {
     313        if (values_sort && Boolean.TRUE.equals(TaggingPresets.SORT_MENU.get())) {
    313314            presetListEntries.sort((a, b) -> AlphanumComparator.getInstance().compare(a.getDisplayValue(), b.getDisplayValue()));
    314315        }
     
    341342            initialValue = DIFFERENT;
    342343            originalValue = initialValue;
    343         } else if (!usage.hadKeys() || isForceUseLastAsDefault() || PROP_FILL_DEFAULT.get()) {
     344        } else if (!usage.hadKeys() || isForceUseLastAsDefault() || Boolean.TRUE.equals(PROP_FILL_DEFAULT.get())) {
    344345            // at this point no primitive had any value for this key
    345346            if (!support.isPresetInitiallyMatches() && isUseLastAsDefault() && LAST_VALUES.containsKey(key)) {
     
    404405
    405406    /**
     407     * Get the entries for this {@link ComboMultiSelect} object
     408     * @return The {@link PresetListEntry} values for this object
     409     */
     410    public List<PresetListEntry> presetListEntries() {
     411        return Collections.unmodifiableList(this.presetListEntries);
     412    }
     413
     414    /**
    406415     * Adds a preset list entry.
    407416     * @param e list entry to add
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/KeyedItem.java

    r18871 r18918  
    22package org.openstreetmap.josm.gui.tagging.presets.items;
    33
     4import static org.openstreetmap.josm.tools.I18n.marktr;
    45import static org.openstreetmap.josm.tools.I18n.tr;
    56
     
    89import java.util.HashMap;
    910import java.util.Map;
     11import java.util.NoSuchElementException;
    1012import java.util.SortedMap;
    11 import java.util.NoSuchElementException;
    1213import java.util.TreeMap;
    1314
     
    2526 * Preset item associated to an OSM key.
    2627 */
    27 public abstract class KeyedItem extends TextItem {
     28public abstract class KeyedItem extends TextItem implements RegionSpecific {
    2829
    2930    /** The constant value {@code "<different>"}. */
    30     protected static final String DIFFERENT = "<different>";
     31    protected static final String DIFFERENT = marktr("<different>");
    3132    /** Translation of {@code "<different>"}. */
    32     public static final String DIFFERENT_I18N = tr("<different>");
     33    public static final String DIFFERENT_I18N = tr(DIFFERENT);
    3334
    3435    /** True if the default value should also be set on primitives that already have tags.  */
     
    5253     */
    5354    public String match = getDefaultMatch().getValue(); // NOSONAR
     55
     56    /**
     57     * List of regions the preset is applicable for.
     58     */
     59    private Collection<String> regions;
     60    /**
     61     * If true, invert the meaning of regions.
     62     */
     63    private boolean excludeRegions;
    5464
    5565    /**
     
    262272
    263273    @Override
     274    public final Collection<String> regions() {
     275        return this.regions;
     276    }
     277
     278    @Override
     279    public final void realSetRegions(Collection<String> regions) {
     280        this.regions = regions;
     281    }
     282
     283    @Override
     284    public final boolean exclude_regions() {
     285        return this.excludeRegions;
     286    }
     287
     288    @Override
     289    public final void setExclude_regions(boolean excludeRegions) {
     290        this.excludeRegions = excludeRegions;
     291    }
     292
     293    @Override
    264294    public String toString() {
    265295        return "KeyedItem [key=" + key + ", text=" + text
  • trunk/src/org/openstreetmap/josm/gui/tagging/presets/items/PresetListEntry.java

    r18801 r18918  
    66import static org.openstreetmap.josm.tools.I18n.trc;
    77
     8import java.util.Collection;
    89import java.util.Objects;
    910
     
    2122 * {@link MultiSelect}.
    2223 */
    23 public class PresetListEntry implements Comparable<PresetListEntry> {
     24public class PresetListEntry implements Comparable<PresetListEntry>, RegionSpecific {
    2425    /** Used to display an entry matching several different values. */
    2526    protected static final PresetListEntry ENTRY_DIFFERENT = new PresetListEntry(KeyedItem.DIFFERENT, null);
     
    4849    public String locale_short_description; // NOSONAR
    4950
     51    /**
     52     * List of regions the entry is applicable for.
     53     */
     54    private Collection<String> regions;
     55
     56    /**
     57     * If true, invert the meaning of regions.
     58     */
     59    private boolean excludeRegions;
     60
    5061    private String cachedDisplayValue;
    5162    private String cachedShortDescription;
     
    5465    /**
    5566     * Constructs a new {@code PresetListEntry}, uninitialized.
    56      *
     67     * <p>
    5768     * Public default constructor is needed by {@link org.openstreetmap.josm.tools.XmlObjectParser.Parser#startElement}
    5869     */
     
    7485    /**
    7586     * Returns the contents displayed in the dropdown list.
    76      *
     87     * <p>
    7788     * This is the contents that would be displayed in the current view plus a short description to
    7889     * aid the user. The whole content is wrapped to {@code width}.
     
    164175    }
    165176
     177    @Override
     178    public Collection<String> regions() {
     179        return this.regions;
     180    }
     181
     182    @Override
     183    public void realSetRegions(Collection<String> regions) {
     184        this.regions = regions;
     185    }
     186
     187    @Override
     188    public boolean exclude_regions() {
     189        return this.excludeRegions;
     190    }
     191
     192    @Override
     193    public void setExclude_regions(boolean excludeRegions) {
     194        this.excludeRegions = excludeRegions;
     195    }
     196
    166197    // toString is mainly used to initialize the Editor
    167198    @Override
  • trunk/src/org/openstreetmap/josm/io/imagery/WMSImagery.java

    r18871 r18918  
    165165     * @throws WMSGetCapabilitiesException when there are errors when parsing get capabilities document
    166166     * @throws InvalidPathException if a Path object cannot be constructed for the capabilities cached file
    167      * @since xxx
     167     * @since 18780
    168168     */
    169169    public WMSImagery(String url, Map<String, String> headers, ProgressMonitor monitor)
Note: See TracChangeset for help on using the changeset viewer.