Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java	(revision 17761)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactory.java	(revision 17762)
@@ -2,8 +2,9 @@
 package org.openstreetmap.josm.gui.mappaint.mapcss;
 
-import java.lang.reflect.Method;
 import java.text.MessageFormat;
-import java.util.Arrays;
 import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
@@ -33,5 +34,4 @@
 import org.openstreetmap.josm.gui.mappaint.mapcss.Condition.TagCondition;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
-import org.openstreetmap.josm.tools.JosmRuntimeException;
 import org.openstreetmap.josm.tools.Utils;
 
@@ -883,10 +883,36 @@
     public static class PseudoClassCondition implements Condition {
 
-        final Method method;
-        final boolean not;
-
-        protected PseudoClassCondition(Method method, boolean not) {
-            this.method = method;
-            this.not = not;
+        static final Map<String, PseudoClassCondition> CONDITION_MAP = new HashMap<>();
+
+        static {
+            PseudoClassCondition.register("anticlockwise", PseudoClasses::anticlockwise);
+            PseudoClassCondition.register("areaStyle", PseudoClasses::areaStyle);
+            PseudoClassCondition.register("clockwise", PseudoClasses::clockwise);
+            PseudoClassCondition.register("closed", PseudoClasses::closed);
+            PseudoClassCondition.register("closed2", PseudoClasses::closed2);
+            PseudoClassCondition.register("completely_downloaded", PseudoClasses::completely_downloaded);
+            PseudoClassCondition.register("connection", PseudoClasses::connection);
+            PseudoClassCondition.register("inDownloadedArea", PseudoClasses::inDownloadedArea);
+            PseudoClassCondition.register("modified", PseudoClasses::modified);
+            PseudoClassCondition.register("new", PseudoClasses::_new);
+            PseudoClassCondition.register("righthandtraffic", PseudoClasses::righthandtraffic);
+            PseudoClassCondition.register("sameTags", PseudoClasses::sameTags);
+            PseudoClassCondition.register("selected", PseudoClasses::selected);
+            PseudoClassCondition.register("tagged", PseudoClasses::tagged);
+            PseudoClassCondition.register("unclosed_multipolygon", PseudoClasses::unclosed_multipolygon);
+            PseudoClassCondition.register("unconnected", PseudoClasses::unconnected);
+        }
+
+        private static void register(String name, Predicate<Environment> predicate) {
+            CONDITION_MAP.put(clean(name), new PseudoClassCondition(":" + name, predicate));
+            CONDITION_MAP.put("!" + clean(name), new PseudoClassCondition("!:" + name, predicate.negate()));
+        }
+
+        private final String name;
+        private final Predicate<Environment> predicate;
+
+        protected PseudoClassCondition(String name, Predicate<Environment> predicate) {
+            this.name = name;
+            this.predicate = predicate;
         }
 
@@ -903,35 +929,25 @@
                 return new OpenEndPseudoClassCondition(not);
             }
-            final Method method = getMethod(id);
-            if (method != null) {
-                return new PseudoClassCondition(method, not);
+            String cleanId = not ? clean("!" + id) : clean(id);
+            PseudoClassCondition condition = CONDITION_MAP.get(cleanId);
+            if (condition != null) {
+                return condition;
             }
             throw new MapCSSException("Invalid pseudo class specified: " + id);
-        }
-
-        protected static Method getMethod(String id) {
-            String cleanId = clean(id);
-            return Arrays.stream(PseudoClasses.class.getDeclaredMethods())
-                    .filter(method -> clean(method.getName()).equalsIgnoreCase(cleanId))
-                    .findFirst().orElse(null);
         }
 
         private static String clean(String id) {
             // for backwards compatibility, consider :sameTags == :same-tags == :same_tags (#11150)
-            return id.replaceAll("[-_]", "");
+            return id.toLowerCase(Locale.ROOT).replaceAll("[-_]", "");
         }
 
         @Override
         public boolean applies(Environment e) {
-            try {
-                return not ^ (Boolean) method.invoke(null, e);
-            } catch (ReflectiveOperationException ex) {
-                throw new JosmRuntimeException(ex);
-            }
+            return predicate.test(e);
         }
 
         @Override
         public String toString() {
-            return (not ? "!" : "") + ':' + method.getName();
+            return name;
         }
     }
@@ -941,4 +957,5 @@
      */
     public static class OpenEndPseudoClassCondition extends PseudoClassCondition {
+        final boolean not;
         /**
          * Constructs a new {@code OpenEndPseudoClassCondition}.
@@ -946,10 +963,11 @@
          */
         public OpenEndPseudoClassCondition(boolean not) {
-            super(null, not);
+            super("open_end", null);
+            this.not = not;
         }
 
         @Override
         public boolean applies(Environment e) {
-            return true;
+            return !not;
         }
     }
Index: /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactoryTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactoryTest.java	(revision 17761)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/ConditionFactoryTest.java	(revision 17762)
@@ -13,4 +13,6 @@
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import net.trajano.commons.testing.UtilityClassTestUtil;
+
+import java.lang.reflect.Method;
 
 /**
@@ -43,3 +45,16 @@
         UtilityClassTestUtil.assertUtilityClassWellDefined(PseudoClasses.class);
     }
+
+    /**
+     * Tests that all functions have been registered to {@link ConditionFactory.PseudoClassCondition#CONDITION_MAP}
+     */
+    @Test
+    void testAllPseudoClassesRegistered() {
+        for (Method method : PseudoClasses.class.getDeclaredMethods()) {
+            String name = method.getName().replaceFirst("^_new$", "new");
+            Context context = name.equals("sameTags") ? Context.LINK : Context.PRIMITIVE;
+            ConditionFactory.PseudoClassCondition.createPseudoClassCondition(name, false, context);
+            ConditionFactory.PseudoClassCondition.createPseudoClassCondition(name, true, context);
+        }
+    }
 }
Index: /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java	(revision 17761)
+++ /trunk/test/unit/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParserTest.java	(revision 17762)
@@ -89,10 +89,18 @@
     @Test
     void testPseudoClassCondition() throws Exception {
+        Condition c0 = ((Selector.GeneralSelector) getParser("way:area-style").selector()).conds.get(0);
         Condition c1 = ((Selector.GeneralSelector) getParser("way!:area-style").selector()).conds.get(0);
         Condition c2 = ((Selector.GeneralSelector) getParser("way!:areaStyle").selector()).conds.get(0);
         Condition c3 = ((Selector.GeneralSelector) getParser("way!:area_style").selector()).conds.get(0);
+        assertEquals(":areaStyle", c0.toString());
         assertEquals("!:areaStyle", c1.toString());
         assertEquals("!:areaStyle", c2.toString());
         assertEquals("!:areaStyle", c3.toString());
+        Selector tagged = getParser("way:tagged").selector();
+        Selector notTagged = getParser("way!:tagged").selector();
+        assertFalse(tagged.matches((new Environment(OsmUtils.createPrimitive("way")))));
+        assertTrue(tagged.matches((new Environment(OsmUtils.createPrimitive("way building=yes")))));
+        assertTrue(notTagged.matches((new Environment(OsmUtils.createPrimitive("way")))));
+        assertFalse(notTagged.matches((new Environment(OsmUtils.createPrimitive("way building=yes")))));
     }
 
