Ticket #13901: mapcss-tag2link.patch

File mapcss-tag2link.patch, 16.6 KB (added by simon04, 4 years ago)
  • src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java

    commit ca1b0013680e30cc419f726fab6282f488084531
    Author: Simon Legner <Simon.Legner@gmail.com>
    Date:   Fri Jan 11 17:43:05 2019 +0100
    
        v1
    
    diff --git a/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java b/src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
    index 31d9438b8..9d70b60da 100644
    a b  
    4141import org.openstreetmap.josm.data.osm.OsmUtils;
    4242import org.openstreetmap.josm.data.osm.Relation;
    4343import org.openstreetmap.josm.data.osm.Tag;
     44import org.openstreetmap.josm.data.osm.Tagged;
    4445import org.openstreetmap.josm.data.osm.Way;
    4546import org.openstreetmap.josm.data.preferences.sources.SourceEntry;
    4647import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;
     
    4950import org.openstreetmap.josm.data.validation.Test;
    5051import org.openstreetmap.josm.data.validation.TestError;
    5152import org.openstreetmap.josm.gui.mappaint.Environment;
    52 import org.openstreetmap.josm.gui.mappaint.Keyword;
    5353import org.openstreetmap.josm.gui.mappaint.MultiCascade;
    5454import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
    5555import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.ClassCondition;
    public ParseResult(List<TagCheck> parseChecks, Collection<Throwable> parseErrors  
    286286        protected final GroupedMapCSSRule rule;
    287287        /** Commands to apply in order to fix a matching primitive */
    288288        protected final List<FixCommand> fixCommands = new ArrayList<>();
    289         /** Tags (or arbitraty strings) of alternatives to be presented to the user */
     289        /** Tags (or arbitrary strings) of alternatives to be presented to the user */
    290290        protected final List<String> alternatives = new ArrayList<>();
    291291        /** An {@link org.openstreetmap.josm.gui.mappaint.mapcss.Instruction.AssignmentInstruction}-{@link Severity} pair.
    292292         * Is evaluated on the matching primitive to give the error message. Map is checked to contain exactly one element. */
    static TagCheck ofMapCSSRule(final GroupedMapCSSRule rule) throws IllegalDataExc  
    329329                        continue;
    330330                    }
    331331                    try {
    332                         final String val = ai.val instanceof Expression
    333                                 ? Optional.ofNullable(((Expression) ai.val).evaluate(new Environment())).map(Object::toString).orElse(null)
    334                                 : ai.val instanceof String
    335                                 ? (String) ai.val
    336                                 : ai.val instanceof Keyword
    337                                 ? ((Keyword) ai.val).val
    338                                 : null;
     332                        final String val = ai.getValAsString();
    339333                        if (ai.key.startsWith("throw")) {
    340334                            try {
    341335                                check.errors.put(ai, Severity.valueOf(ai.key.substring("throw".length()).toUpperCase(Locale.ENGLISH)));
    Selector whichSelectorMatchesEnvironment(Environment env) {  
    445439         * @param matchingSelector matching selector
    446440         * @param index index
    447441         * @param type selector type ("key", "value" or "tag")
    448          * @param p OSM primitive
     442         * @param p a tagged object
    449443         * @return argument value, can be {@code null}
    450444         */
    451         static String determineArgument(OptimizedGeneralSelector matchingSelector, int index, String type, OsmPrimitive p) {
     445        static String determineArgument(OptimizedGeneralSelector matchingSelector, int index, String type, Tagged p) {
    452446            try {
    453447                final Condition c = matchingSelector.getConditions().get(index);
    454                 final Tag tag = c instanceof Condition.ToTagConvertable
    455                         ? ((Condition.ToTagConvertable) c).asTag(p)
     448                final Tag tag = c instanceof Condition.TagCondition
     449                        ? ((Condition.TagCondition) c).asTag(p)
    456450                        : null;
    457451                if (tag == null) {
    458452                    return null;
    static String determineArgument(OptimizedGeneralSelector matchingSelector, int i  
    474468         * key/value/tag of the {@code index}-th {@link Condition} of {@code matchingSelector}.
    475469         * @param matchingSelector matching selector
    476470         * @param s any string
    477          * @param p OSM primitive
     471         * @param p a tagged object
    478472         * @return string with arguments inserted
    479473         */
    480         static String insertArguments(Selector matchingSelector, String s, OsmPrimitive p) {
     474        static String insertArguments(Selector matchingSelector, String s, Tagged p) {
    481475            if (s != null && matchingSelector instanceof Selector.ChildOrParentSelector) {
    482476                return insertArguments(((Selector.ChildOrParentSelector) matchingSelector).right, s, p);
    483477            } else if (s == null || !(matchingSelector instanceof Selector.OptimizedGeneralSelector)) {
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java

    diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Condition.java
    index f0eab71e3..d10aa1be9 100644
    a b  
    33
    44import org.openstreetmap.josm.data.osm.OsmPrimitive;
    55import org.openstreetmap.josm.data.osm.Tag;
     6import org.openstreetmap.josm.data.osm.Tagged;
    67import org.openstreetmap.josm.gui.mappaint.Environment;
     8import org.openstreetmap.josm.tools.Utils;
    79
    810/**
    911 * This is a condition that needs to be fulfilled in order to apply a MapCSS style.
     
    3840     * @author Michael Zangl
    3941     * @since 10674
    4042     */
    41     @FunctionalInterface
    42     interface ToTagConvertable {
     43    interface TagCondition extends Condition {
     44
     45        @Override
     46        default boolean applies(Environment e) {
     47            return applies(e.osm);
     48        }
     49
     50        /**
     51         * Checks if the condition applies in the given {@link Tagged} element.
     52         * @param tagged The tagged to check.
     53         * @return <code>true</code> if the condition applies.
     54         */
     55        boolean applies(Tagged tagged);
     56
    4357        /**
    4458         * Converts the current condition to a tag
    45          * @param primitive A primitive to use as context. May be ignored.
     59         * @param tagged A tagged object to use as context. May be ignored.
    4660         * @return A tag with the key/value of this condition.
    4761         */
    48         Tag asTag(OsmPrimitive primitive);
     62        Tag asTag(Tagged tagged);
    4963    }
    5064}
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java

    diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java
    index e0cc01b46..29d6ce2a1 100644
    a b  
    2323import org.openstreetmap.josm.data.osm.OsmUtils;
    2424import org.openstreetmap.josm.data.osm.Relation;
    2525import org.openstreetmap.josm.data.osm.Tag;
     26import org.openstreetmap.josm.data.osm.Tagged;
    2627import org.openstreetmap.josm.data.osm.search.SearchCompiler.InDataSourceArea;
    2728import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
    2829import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
     
    3031import org.openstreetmap.josm.gui.mappaint.ElemStyles;
    3132import org.openstreetmap.josm.gui.mappaint.Environment;
    3233import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    33 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable;
     34import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;
    3435import org.openstreetmap.josm.tools.CheckParameterUtil;
    3536import org.openstreetmap.josm.tools.JosmRuntimeException;
    3637import org.openstreetmap.josm.tools.Utils;
    public boolean eval(String testString, String prototypeString) {  
    243244     *
    244245     * Extra class for performance reasons.
    245246     */
    246     public static class SimpleKeyValueCondition implements Condition, ToTagConvertable {
     247    public static class SimpleKeyValueCondition implements TagCondition {
    247248        /**
    248249         * The key to search for.
    249250         */
    public SimpleKeyValueCondition(String k, String v) {  
    264265        }
    265266
    266267        @Override
    267         public boolean applies(Environment e) {
    268             return v.equals(e.osm.get(k));
     268        public boolean applies(Tagged tagged) {
     269            return v.equals(tagged.get(k));
    269270        }
    270271
    271272        @Override
    272         public Tag asTag(OsmPrimitive primitive) {
     273        public Tag asTag(Tagged tagged) {
    273274            return new Tag(k, v);
    274275        }
    275276
    public String toString() {  
    284285     * <p>Represents a key/value condition which is either applied to a primitive.</p>
    285286     *
    286287     */
    287     public static class KeyValueCondition implements Condition, ToTagConvertable {
     288    public static class KeyValueCondition implements TagCondition {
    288289        /**
    289290         * The key to search for.
    290291         */
    public boolean requiresExactKeyMatch() {  
    327328        }
    328329
    329330        @Override
    330         public boolean applies(Environment env) {
    331             return op.eval(env.osm.get(k), considerValAsKey ? env.osm.get(v) : v);
     331        public boolean applies(Tagged tagged) {
     332            return op.eval(tagged.get(k), considerValAsKey ? tagged.get(v) : v);
    332333        }
    333334
    334335        @Override
    335         public Tag asTag(OsmPrimitive primitive) {
     336        public Tag asTag(Tagged tagged) {
    336337            return new Tag(k, v);
    337338        }
    338339
    public boolean applies(Environment env) {  
    512513     *                   LINK:       not supported
    513514     * </pre>
    514515     */
    515     public static class KeyCondition implements Condition, ToTagConvertable {
     516    public static class KeyCondition implements TagCondition {
    516517
    517518        /**
    518519         * The key name.
    public KeyCondition(String label, boolean negateResult, KeyMatchType matchType)  
    550551        @Override
    551552        public boolean applies(Environment e) {
    552553            switch(e.getContext()) {
    553             case PRIMITIVE:
    554                 switch (matchType) {
     554                case PRIMITIVE:
     555                    return applies(e.osm);
     556                case LINK:
     557                    Utils.ensure(false, "Illegal state: {0} not supported in LINK context", getClass());
     558                    return false;
     559                default: throw new AssertionError();
     560            }
     561        }
     562
     563        @Override
     564        public boolean applies(Tagged tagged) {
     565            switch (matchType) {
    555566                case TRUE:
    556                     return e.osm.isKeyTrue(label) ^ negateResult;
     567                    return tagged.isKeyTrue(label) ^ negateResult;
    557568                case FALSE:
    558                     return e.osm.isKeyFalse(label) ^ negateResult;
     569                    return tagged.isKeyFalse(label) ^ negateResult;
    559570                case REGEX:
    560                     return e.osm.keySet().stream().anyMatch(containsPattern) ^ negateResult;
     571                    return tagged.keySet().stream().anyMatch(containsPattern) ^ negateResult;
    561572                default:
    562                     return e.osm.hasKey(label) ^ negateResult;
    563                 }
    564             case LINK:
    565                 Utils.ensure(false, "Illegal state: KeyCondition not supported in LINK context");
    566                 return false;
    567             default: throw new AssertionError();
     573                    return tagged.hasKey(label) ^ negateResult;
    568574            }
    569575        }
    570576
    public boolean applies(Environment e) {  
    578584         * @return The tag.
    579585         */
    580586        @Override
    581         public Tag asTag(OsmPrimitive p) {
     587        public Tag asTag(Tagged p) {
    582588            String key = label;
    583589            if (KeyMatchType.REGEX == matchType) {
    584590                key = p.keySet().stream().filter(containsPattern).findAny().orElse(key);
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java

    diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/Instruction.java
    index 793b85eaa..58b4082d8 100644
    a b  
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
    44import java.util.Arrays;
     5import java.util.Optional;
    56
    67import org.openstreetmap.josm.gui.mappaint.Cascade;
    78import org.openstreetmap.josm.gui.mappaint.Environment;
    public void execute(Environment env) {  
    102103            env.mc.getOrCreateCascade(env.layer).putOrClear(key, value);
    103104        }
    104105
     106        public String getValAsString() {
     107            return this.val instanceof Expression
     108                    ? Optional.ofNullable(((Expression) this.val).evaluate(new Environment())).map(Object::toString).orElse(null)
     109                    : this.val instanceof String
     110                    ? (String) this.val
     111                    : this.val instanceof Keyword
     112                    ? ((Keyword) this.val).val
     113                    : null;
     114        }
     115
    105116        @Override
    106117        public String toString() {
    107118            return key + ": " + (val instanceof float[] ? Arrays.toString((float[]) val) :
  • src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java

    diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSRule.java
    index fca2760f4..511fd351c 100644
    a b  
    4343
    4444        /**
    4545         * Create a new {@link Declaration}
    46          * @param instructions The instructions for this dectlaration
     46         * @param instructions The instructions for this declaration
    4747         * @param idx The index in the {@link StyleSource}
    4848         */
    4949        public Declaration(List<Instruction> instructions, int idx) {
  • new file src/org/openstreetmap/josm/tools/Tag2Link.java

    diff --git a/src/org/openstreetmap/josm/tools/Tag2Link.java b/src/org/openstreetmap/josm/tools/Tag2Link.java
    new file mode 100644
    index 000000000..e9490c14b
    - +  
     1package org.openstreetmap.josm.tools;
     2
     3import java.net.URL;
     4import java.util.ArrayList;
     5import java.util.List;
     6
     7import org.openstreetmap.josm.data.osm.Tag;
     8import org.openstreetmap.josm.gui.mappaint.mapcss.Condition;
     9import org.openstreetmap.josm.gui.mappaint.mapcss.MapCSSRule;
     10import org.openstreetmap.josm.gui.mappaint.mapcss.Selector;
     11
     12public final class Tag2Link {
     13
     14    final List<MapCSSRule> rules = new ArrayList<>();
     15
     16    private Tag2Link() {
     17    }
     18
     19    public Iterable<URL> getLinksForTag(Tag tag) {
     20        for (MapCSSRule rule : rules) {
     21            for (Condition condition : ((Selector.AbstractSelector) rule.selector).getConditions()) {
     22                if (((Condition.TagCondition) condition).applies(tag)) {
     23
     24                }
     25            }
     26        }
     27    }
     28}
  • test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java

    diff --git a/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java b/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionTest.java
    index 4fefb417e..890f311ba 100644
    a b  
    1212import org.openstreetmap.josm.data.osm.OsmUtils;
    1313import org.openstreetmap.josm.gui.mappaint.Environment;
    1414import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.Context;
    15 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.ToTagConvertable;
     15import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;
    1616import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.Op;
    1717import org.openstreetmap.josm.gui.mappaint.mapcss.ConditionFactory.SimpleKeyValueCondition;
    1818import org.openstreetmap.josm.testutils.JOSMTestRules;
    public void testKeyValueEq() {  
    6262
    6363        assertTrue(op instanceof SimpleKeyValueCondition);
    6464        assertEquals("[k1=v1]", op.toString());
    65         assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey());
    66         assertEquals("v1", ((ToTagConvertable) op).asTag(null).getValue());
     65        assertEquals("k1", ((TagCondition) op).asTag(null).getKey());
     66        assertEquals("v1", ((TagCondition) op).asTag(null).getValue());
    6767    }
    6868
    6969    /**
    public void testKeyValueEqAsKey() {  
    7878        assertFalse(op.applies(genEnv(node3)));
    7979        assertFalse(op.applies(genEnv(node4)));
    8080
    81         assertEquals("k1", ((ToTagConvertable) op).asTag(null).getKey());
    82         assertEquals("k2", ((ToTagConvertable) op).asTag(null).getValue());
     81        assertEquals("k1", ((TagCondition) op).asTag(null).getKey());
     82        assertEquals("k2", ((TagCondition) op).asTag(null).getValue());
    8383    }
    8484
    8585    /**