Changeset 17762 in josm


Ignore:
Timestamp:
2021-04-12T22:43:33+02:00 (4 years ago)
Author:
simon04
Message:

see #20744 - Evaluate MapCSS pseudo classes without array creation

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java

    r17745 r17762  
    22package org.openstreetmap.josm.gui.mappaint.mapcss;
    33
    4 import java.lang.reflect.Method;
    54import java.text.MessageFormat;
    6 import java.util.Arrays;
    75import java.util.EnumSet;
     6import java.util.HashMap;
     7import java.util.Locale;
     8import java.util.Map;
    89import java.util.Objects;
    910import java.util.Set;
     
    3334import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;
    3435import org.openstreetmap.josm.tools.CheckParameterUtil;
    35 import org.openstreetmap.josm.tools.JosmRuntimeException;
    3636import org.openstreetmap.josm.tools.Utils;
    3737
     
    883883    public static class PseudoClassCondition implements Condition {
    884884
    885         final Method method;
    886         final boolean not;
    887 
    888         protected PseudoClassCondition(Method method, boolean not) {
    889             this.method = method;
    890             this.not = not;
     885        static final Map<String, PseudoClassCondition> CONDITION_MAP = new HashMap<>();
     886
     887        static {
     888            PseudoClassCondition.register("anticlockwise", PseudoClasses::anticlockwise);
     889            PseudoClassCondition.register("areaStyle", PseudoClasses::areaStyle);
     890            PseudoClassCondition.register("clockwise", PseudoClasses::clockwise);
     891            PseudoClassCondition.register("closed", PseudoClasses::closed);
     892            PseudoClassCondition.register("closed2", PseudoClasses::closed2);
     893            PseudoClassCondition.register("completely_downloaded", PseudoClasses::completely_downloaded);
     894            PseudoClassCondition.register("connection", PseudoClasses::connection);
     895            PseudoClassCondition.register("inDownloadedArea", PseudoClasses::inDownloadedArea);
     896            PseudoClassCondition.register("modified", PseudoClasses::modified);
     897            PseudoClassCondition.register("new", PseudoClasses::_new);
     898            PseudoClassCondition.register("righthandtraffic", PseudoClasses::righthandtraffic);
     899            PseudoClassCondition.register("sameTags", PseudoClasses::sameTags);
     900            PseudoClassCondition.register("selected", PseudoClasses::selected);
     901            PseudoClassCondition.register("tagged", PseudoClasses::tagged);
     902            PseudoClassCondition.register("unclosed_multipolygon", PseudoClasses::unclosed_multipolygon);
     903            PseudoClassCondition.register("unconnected", PseudoClasses::unconnected);
     904        }
     905
     906        private static void register(String name, Predicate<Environment> predicate) {
     907            CONDITION_MAP.put(clean(name), new PseudoClassCondition(":" + name, predicate));
     908            CONDITION_MAP.put("!" + clean(name), new PseudoClassCondition("!:" + name, predicate.negate()));
     909        }
     910
     911        private final String name;
     912        private final Predicate<Environment> predicate;
     913
     914        protected PseudoClassCondition(String name, Predicate<Environment> predicate) {
     915            this.name = name;
     916            this.predicate = predicate;
    891917        }
    892918
     
    903929                return new OpenEndPseudoClassCondition(not);
    904930            }
    905             final Method method = getMethod(id);
    906             if (method != null) {
    907                 return new PseudoClassCondition(method, not);
     931            String cleanId = not ? clean("!" + id) : clean(id);
     932            PseudoClassCondition condition = CONDITION_MAP.get(cleanId);
     933            if (condition != null) {
     934                return condition;
    908935            }
    909936            throw new MapCSSException("Invalid pseudo class specified: " + id);
    910         }
    911 
    912         protected static Method getMethod(String id) {
    913             String cleanId = clean(id);
    914             return Arrays.stream(PseudoClasses.class.getDeclaredMethods())
    915                     .filter(method -> clean(method.getName()).equalsIgnoreCase(cleanId))
    916                     .findFirst().orElse(null);
    917937        }
    918938
    919939        private static String clean(String id) {
    920940            // for backwards compatibility, consider :sameTags == :same-tags == :same_tags (#11150)
    921             return id.replaceAll("[-_]", "");
     941            return id.toLowerCase(Locale.ROOT).replaceAll("[-_]", "");
    922942        }
    923943
    924944        @Override
    925945        public boolean applies(Environment e) {
    926             try {
    927                 return not ^ (Boolean) method.invoke(null, e);
    928             } catch (ReflectiveOperationException ex) {
    929                 throw new JosmRuntimeException(ex);
    930             }
     946            return predicate.test(e);
    931947        }
    932948
    933949        @Override
    934950        public String toString() {
    935             return (not ? "!" : "") + ':' + method.getName();
     951            return name;
    936952        }
    937953    }
     
    941957     */
    942958    public static class OpenEndPseudoClassCondition extends PseudoClassCondition {
     959        final boolean not;
    943960        /**
    944961         * Constructs a new {@code OpenEndPseudoClassCondition}.
     
    946963         */
    947964        public OpenEndPseudoClassCondition(boolean not) {
    948             super(null, not);
     965            super("open_end", null);
     966            this.not = not;
    949967        }
    950968
    951969        @Override
    952970        public boolean applies(Environment e) {
    953             return true;
     971            return !not;
    954972        }
    955973    }
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactoryTest.java

    r17275 r17762  
    1313import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
    1414import net.trajano.commons.testing.UtilityClassTestUtil;
     15
     16import java.lang.reflect.Method;
    1517
    1618/**
     
    4345        UtilityClassTestUtil.assertUtilityClassWellDefined(PseudoClasses.class);
    4446    }
     47
     48    /**
     49     * Tests that all functions have been registered to {@link ConditionFactory.PseudoClassCondition#CONDITION_MAP}
     50     */
     51    @Test
     52    void testAllPseudoClassesRegistered() {
     53        for (Method method : PseudoClasses.class.getDeclaredMethods()) {
     54            String name = method.getName().replaceFirst("^_new$", "new");
     55            Context context = name.equals("sameTags") ? Context.LINK : Context.PRIMITIVE;
     56            ConditionFactory.PseudoClassCondition.createPseudoClassCondition(name, false, context);
     57            ConditionFactory.PseudoClassCondition.createPseudoClassCondition(name, true, context);
     58        }
     59    }
    4560}
  • trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java

    r17760 r17762  
    8989    @Test
    9090    void testPseudoClassCondition() throws Exception {
     91        Condition c0 = ((Selector.GeneralSelector) getParser("way:area-style").selector()).conds.get(0);
    9192        Condition c1 = ((Selector.GeneralSelector) getParser("way!:area-style").selector()).conds.get(0);
    9293        Condition c2 = ((Selector.GeneralSelector) getParser("way!:areaStyle").selector()).conds.get(0);
    9394        Condition c3 = ((Selector.GeneralSelector) getParser("way!:area_style").selector()).conds.get(0);
     95        assertEquals(":areaStyle", c0.toString());
    9496        assertEquals("!:areaStyle", c1.toString());
    9597        assertEquals("!:areaStyle", c2.toString());
    9698        assertEquals("!:areaStyle", c3.toString());
     99        Selector tagged = getParser("way:tagged").selector();
     100        Selector notTagged = getParser("way!:tagged").selector();
     101        assertFalse(tagged.matches((new Environment(OsmUtils.createPrimitive("way")))));
     102        assertTrue(tagged.matches((new Environment(OsmUtils.createPrimitive("way building=yes")))));
     103        assertTrue(notTagged.matches((new Environment(OsmUtils.createPrimitive("way")))));
     104        assertFalse(notTagged.matches((new Environment(OsmUtils.createPrimitive("way building=yes")))));
    97105    }
    98106
Note: See TracChangeset for help on using the changeset viewer.