Changeset 6534 in josm


Ignore:
Timestamp:
2013-12-26T01:43:30+01:00 (10 years ago)
Author:
simon04
Message:

fix #9470 see #9414 - make "layer tag with + sign" auto fixable

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/data/validator/numeric.mapcss

    r6532 r6534  
    33*[layer =~ /\+.*/] {
    44  throwWarning: tr("layer tag with + sign");
     5  fixAdd: concat("layer=", replace(tag("layer"), "+", ""));
    56  assertMatch: "node layer=+1";
    67  assertNoMatch: "node layer=1";
  • trunk/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    r6532 r6534  
    2929import org.openstreetmap.josm.data.validation.TestError;
    3030import org.openstreetmap.josm.gui.mappaint.Environment;
    31 import org.openstreetmap.josm.gui.mappaint.mapcss.ExpressionFactory;
     31import org.openstreetmap.josm.gui.mappaint.mapcss.Expression;
    3232import org.openstreetmap.josm.gui.mappaint.mapcss.Instruction;
    3333import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
     
    5757    static class TagCheck implements Predicate<OsmPrimitive> {
    5858        protected final List<Selector> selector;
    59         protected final List<Tag> change = new ArrayList<Tag>();
     59        protected final List<PrimitiveToTag> change = new ArrayList<PrimitiveToTag>();
    6060        protected final Map<String, String> keyChange = new LinkedHashMap<String, String>();
    6161        protected final List<Tag> alternatives = new ArrayList<Tag>();
     
    6565        TagCheck(List<Selector> selector) {
    6666            this.selector = selector;
     67        }
     68
     69        /**
     70         * A function mapping the matched {@link OsmPrimitive} to a {@link Tag}.
     71         */
     72        static abstract class PrimitiveToTag implements Utils.Function<OsmPrimitive, Tag> {
     73
     74            /**
     75             * Creates a new mapping from an {@code MapCSS} object.
     76             * In case of an {@link Expression}, that is evaluated on the matched {@link OsmPrimitive}.
     77             * In case of a {@link String}, that is "compiled" to a {@link Tag} instance.
     78             */
     79            static PrimitiveToTag ofMapCSSObject(final Object obj, final boolean keyOnly) {
     80                if (obj instanceof Expression) {
     81                    return new PrimitiveToTag() {
     82                        @Override
     83                        public Tag apply(OsmPrimitive p) {
     84                            final String s = (String) ((Expression) obj).evaluate(new Environment().withPrimitive(p));
     85                            return keyOnly? new Tag(s) : Tag.ofString(s);
     86                        }
     87                    };
     88                } else if (obj instanceof String) {
     89                    final Tag tag = keyOnly ? new Tag((String) obj) : Tag.ofString((String) obj);
     90                    return new PrimitiveToTag() {
     91                        @Override
     92                        public Tag apply(OsmPrimitive ignore) {
     93                            return tag;
     94                        }
     95                    };
     96                } else {
     97                    return null;
     98                }
     99            }
    67100        }
    68101
     
    72105                if (i instanceof Instruction.AssignmentInstruction) {
    73106                    final Instruction.AssignmentInstruction ai = (Instruction.AssignmentInstruction) i;
    74                     final String val = ai.val instanceof ExpressionFactory.ArrayFunction
    75                             ? (String) ((ExpressionFactory.ArrayFunction) ai.val).evaluate(new Environment())
     107                    final String val = ai.val instanceof Expression
     108                            ? (String) ((Expression) ai.val).evaluate(new Environment())
    76109                            : ai.val instanceof String
    77110                            ? (String) ai.val
     
    80113                        final Severity severity = Severity.valueOf(ai.key.substring("throw".length()).toUpperCase());
    81114                        check.errors.put(val, severity);
    82                     } else if ("fixAdd".equals(ai.key) && val != null) {
    83                         check.change.add(Tag.ofString(val));
    84                     } else if ("fixRemove".equals(ai.key) && val != null) {
    85                         CheckParameterUtil.ensureThat(!val.contains("="), "Unexpected '='. Please only specify the key to remove!");
    86                         check.change.add(new Tag(val));
     115                    } else if ("fixAdd".equals(ai.key)) {
     116                        final PrimitiveToTag toTag = PrimitiveToTag.ofMapCSSObject(ai.val, false);
     117                        check.change.add(toTag);
     118                    } else if ("fixRemove".equals(ai.key)) {
     119                        CheckParameterUtil.ensureThat(!(ai.val instanceof String) || !val.contains("="), "Unexpected '='. Please only specify the key to remove!");
     120                        final PrimitiveToTag toTag = PrimitiveToTag.ofMapCSSObject(ai.val, true);
     121                        check.change.add(toTag);
    87122                    } else if ("fixChangeKey".equals(ai.key) && val != null) {
    88123                        CheckParameterUtil.ensureThat(val.contains("=>"), "Separate old from new key by '=>'!");
     
    159194            }
    160195            Collection<Command> cmds = new LinkedList<Command>();
    161             for (Tag tag : change) {
     196            for (PrimitiveToTag toTag : change) {
     197                final Tag tag = toTag.apply(p);
    162198                cmds.add(new ChangePropertyCommand(p, tag.getKey(), tag.getValue()));
    163199            }
  • trunk/src/org/openstreetmap/josm/gui/mappaint/Cascade.java

    r6322 r6534  
    115115
    116116    private static Float toFloat(Object o) {
    117         if (o instanceof Float)
    118             return (Float) o;
    119         if (o instanceof Double)
    120             return new Float((Double) o);
    121         if (o instanceof Integer)
    122             return new Float((Integer) o);
     117        if (o instanceof Number)
     118            return ((Number) o).floatValue();
    123119        if (o instanceof String && !((String) o).isEmpty()) {
    124120            try {
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ExpressionFactory.java

    r6506 r6534  
    131131        }
    132132
     133        /**
     134         * Creates a list of values, e.g., for the {@code dashes} property.
     135         * @see {@link Arrays#asList(Object[])}
     136         */
    133137        public static List list(Object... args) {
    134138            return Arrays.asList(args);
    135139        }
    136140
    137         public static Object get(List<? extends Object> objects, float index) {
    138             int idx = Math.round(index);
    139             if (idx >= 0 && idx < objects.size()) {
    140                 return objects.get(idx);
     141        /**
     142         * Get the {@code n}th element of the list {@code lst} (counting starts at 0).
     143         * @since 5699
     144         */
     145        public static Object get(List<?> lst, float n) {
     146            int idx = Math.round(n);
     147            if (idx >= 0 && idx < lst.size()) {
     148                return lst.get(idx);
    141149            }
    142150            return null;
    143151        }
    144152
     153        /**
     154         * Splits string {@code toSplit} at occurrences of the separator string {@code sep} and returns a list of matches.
     155         * @see {@link String#split(String)}
     156         * @since 5699
     157         */
    145158        public static List<String> split(String sep, String toSplit) {
    146159            return Arrays.asList(toSplit.split(Pattern.quote(sep), -1));
    147160        }
    148161
     162        /**
     163         * Creates a color value with the specified amounts of {@code r}ed, {@code g}reen, {@code b}lue (arguments from 0.0 to 1.0)
     164         * @see {@link Color#Color(float, float, float)}
     165         */
    149166        public static Color rgb(float r, float g, float b) {
    150167            Color c;
     
    157174        }
    158175
     176        /**
     177         * Creates a color value from an HTML notation, i.e., {@code #rrggbb}.
     178         */
    159179        public static Color html2color(String html) {
    160180            return ColorHelper.html2color(html);
    161181        }
    162182
     183        /**
     184         * Computes the HTML notation ({@code #rrggbb}) for a color value).
     185         */
    163186        public static String color2html(Color c) {
    164187            return ColorHelper.color2html(c);
    165188        }
    166189
     190        /**
     191         * Get the value of the red color channel in the rgb color model
     192         * @see {@link java.awt.Color#getRed()}
     193         */
    167194        public static float red(Color c) {
    168195            return Utils.color_int2float(c.getRed());
    169196        }
    170197
     198        /**
     199         * Get the value of the green color channel in the rgb color model
     200         * @see {@link java.awt.Color#getGreen()}
     201         */
    171202        public static float green(Color c) {
    172203            return Utils.color_int2float(c.getGreen());
    173204        }
    174205
     206        /**
     207         * Get the value of the blue color channel in the rgb color model
     208         * @see {@link java.awt.Color#getBlue()}
     209         */
    175210        public static float blue(Color c) {
    176211            return Utils.color_int2float(c.getBlue());
    177212        }
    178213
     214        /**
     215         * Assembles the strings to one.
     216         */
    179217        public static String concat(Object... args) {
    180218            StringBuilder res = new StringBuilder();
     
    185223        }
    186224
     225        /**
     226         * Returns the value of the property {@code key}, e.g., {@code prop("width")}.
     227         */
    187228        public Object prop(String key) {
    188229            return prop(key, null);
    189230        }
    190231
     232        /**
     233         * Returns the value of the property {@code key} from layer {@code layer}.
     234         */
    191235        public Object prop(String key, String layer) {
    192236            Cascade c;
     
    199243        }
    200244
     245        /**
     246         * Determines whether property {@code key} is set.
     247         */
    201248        public Boolean is_prop_set(String key) {
    202249            return is_prop_set(key, null);
    203250        }
    204251
     252        /**
     253         * Determines whether property {@code key} is set on layer {@code layer}.
     254         */
    205255        public Boolean is_prop_set(String key, String layer) {
    206256            Cascade c;
     
    216266        }
    217267
     268        /**
     269         * Gets the value of the key {@code key} from the object in question.
     270         */
    218271        public String tag(String key) {
    219272            return env.osm.get(key);
    220273        }
    221274
     275        /**
     276         * Gets the first non-null value of the key {@code key} from the object's parent(s).
     277         */
    222278        public String parent_tag(String key) {
    223279            if (env.parent == null) {
     
    234290        }
    235291
     292        /**
     293         * Determines whether the object has a tag with the given key.
     294         */
    236295        public boolean has_tag_key(String key) {
    237296            return env.osm.hasKey(key);
    238297        }
    239298
     299        /**
     300         * Returns the index of node in parent way or member in parent relation.
     301         */
    240302        public Float index() {
    241303            if (env.index == null) {
     
    269331        }
    270332
     333        /**
     334         * Determines if the objects {@code a} and {@code b} are equal.
     335         * @see {@link Object#equals(Object)}
     336         */
    271337        public static boolean equal(Object a, Object b) {
    272338            // make sure the casts are done in a meaningful way, so
     
    282348        }
    283349
    284         public Boolean JOSM_search(String s) {
     350        /**
     351         * Determines whether the JOSM search with {@code searchStr} applies to the object.
     352         */
     353        public Boolean JOSM_search(String searchStr) {
    285354            Match m;
    286355            try {
    287                 m = SearchCompiler.compile(s, false, false);
     356                m = SearchCompiler.compile(searchStr, false, false);
    288357            } catch (ParseError ex) {
    289358                return null;
     
    292361        }
    293362
    294         public static String JOSM_pref(String s, String def) {
    295             String res = Main.pref.get(s, null);
     363        /**
     364         * Obtains the JOSM'key {@link org.openstreetmap.josm.data.Preferences} string for key {@code key},
     365         * and defaults to {@code def} if that is null.
     366         * @see {@link org.openstreetmap.josm.data.Preferences#get(String, String)}
     367         */
     368        public static String JOSM_pref(String key, String def) {
     369            String res = Main.pref.get(key, null);
    296370            return res != null ? res : def;
    297371        }
    298372
    299         public static Color JOSM_pref_color(String s, Color def) {
    300             Color res = Main.pref.getColor(s, null);
     373        /**
     374         * Obtains the JOSM'key {@link org.openstreetmap.josm.data.Preferences} color for key {@code key},
     375         * and defaults to {@code def} if that is null.
     376         * @see {@link org.openstreetmap.josm.data.Preferences#getColor(String, java.awt.Color)}
     377         */
     378        public static Color JOSM_pref_color(String key, Color def) {
     379            Color res = Main.pref.getColor(key, null);
    301380            return res != null ? res : def;
    302381        }
    303382
     383        /**
     384         * Tests if string {@code target} matches pattern {@code pattern}
     385         * @see {@link Pattern#matches(String, CharSequence)}
     386         * @since 5699
     387         */
    304388        public static boolean regexp_test(String pattern, String target) {
    305389            return Pattern.matches(pattern, target);
    306390        }
    307391
     392        /**
     393         * Tests if string {@code target} matches pattern {@code pattern}
     394         * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")
     395         * @since 5699
     396         */
    308397        public static boolean regexp_test(String pattern, String target, String flags) {
    309398            int f = 0;
     
    320409        }
    321410
     411        /**
     412         * Tries to match string against pattern regexp and returns a list of capture groups in case of success.
     413         * The first element (index 0) is the complete match (i.e. string).
     414         * Further elements correspond to the bracketed parts of the regular expression.
     415         * @param flags a string that may contain "i" (case insensitive), "m" (multiline) and "s" ("dot all")
     416         * @since 5701
     417         */
    322418        public static List<String> regexp_match(String pattern, String target, String flags) {
    323419            int f = 0;
     
    343439        }
    344440
     441        /**
     442         * Tries to match string against pattern regexp and returns a list of capture groups in case of success.
     443         * The first element (index 0) is the complete match (i.e. string).
     444         * Further elements correspond to the bracketed parts of the regular expression.
     445         * @since 5701
     446         */
    345447        public static List<String> regexp_match(String pattern, String target) {
    346448            Matcher m = Pattern.compile(pattern).matcher(target);
     
    356458        }
    357459
     460        /**
     461         * Returns the OSM id of the current object.
     462         * @see {@link org.openstreetmap.josm.data.osm.AbstractPrimitive#generateUniqueId()}
     463         */
    358464        public long osm_id() {
    359465            return env.osm.getUniqueId();
    360466        }
    361467
     468        /**
     469         * Translates some text for the current locale. The first argument is the text to translate,
     470         * and the subsequent arguments are parameters for the string indicated by {@code {0}}, {@code {1}}, …
     471         */
    362472        public static String tr(String... args) {
    363473            final String text = args[0];
    364474            System.arraycopy(args, 1, args, 0, args.length - 1);
    365475            return org.openstreetmap.josm.tools.I18n.tr(text, args);
     476        }
     477
     478        /**
     479         * Returns the substring of {@code s} starting at index {@code begin} (inclusive, 0-indexed).
     480         * * @see {@link String#substring(int)}
     481         */
     482        public static String substring(String s, /* due to missing Cascade.convertTo for int*/ float begin) {
     483            return s == null ? null : s.substring((int) begin);
     484        }
     485
     486        /**
     487         * Returns the substring of {@code s} starting at index {@code begin} (inclusive)
     488         * and ending at index {@code end}, (exclusive, 0-indexed).
     489         * @see {@link String#substring(int, int)}
     490         */
     491        public static String substring(String s, float begin, float end) {
     492            return s == null ? null : s.substring((int) begin, (int) end);
     493        }
     494
     495        /**
     496         * Replaces in {@code s} every {@code} target} substring by {@code replacement}.
     497         * * @see {@link String#replace(CharSequence, CharSequence)}
     498         */
     499        public static String replace(String s, String target, String replacement) {
     500            return s == null ? null : s.replace(target, replacement);
    366501        }
    367502    }
  • trunk/test/unit/org/openstreetmap/josm/data/validation/tests/MapCSSTagCheckerTest.java

    r6513 r6534  
    4343        final MapCSSTagChecker.TagCheck check = checks.get(0);
    4444        assertThat(check, notNullValue());
    45         assertThat(check.change.get(0), is(new Tag("natural")));
    46         assertThat(check.change.get(1), is(new Tag("natural", "wetland")));
    47         assertThat(check.change.get(2), is(new Tag("wetland", "marsh")));
     45        assertThat(check.change.get(0).apply(null), is(new Tag("natural")));
     46        assertThat(check.change.get(1).apply(null), is(new Tag("natural", "wetland")));
     47        assertThat(check.change.get(2).apply(null), is(new Tag("wetland", "marsh")));
    4848        assertThat(check.errors.keySet().iterator().next(), is("natural=marsh is deprecated"));
    4949        final Node n1 = new Node();
Note: See TracChangeset for help on using the changeset viewer.