From 0146231166e7dee8f85f072eb576b29dfce3cbe6 Mon Sep 17 00:00:00 2001
From: Jiri Hubacek <jiri.hubacek@gmail.com>
Date: Sat, 8 Sep 2018 14:58:46 +0200
Subject: [PATCH 1/2] =?UTF-8?q?Add=20support=20for=20"not=20element=20of"?=
 =?UTF-8?q?=20operator=20(=E2=88=89)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This patch changes the `matches` method of `ChildOrParentSelector` in a
such way that `ELEMENT_OF` and `NOT_ELEMENT_OF` operators iterate over
the *left* selector.
---
 .../josm/gui/mappaint/mapcss/MapCSSParser.jj       |  3 +++
 .../josm/gui/mappaint/mapcss/Selector.java         | 29 +++++++++++++++++++---
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
index 258bfe79e..c6241391b 100644
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
@@ -215,6 +215,7 @@ TOKEN:
 |   < FULLSTOP: "." >
 |   < DEG: "°" >
 |   < ELEMENT_OF: "∈" >
+|   < NOT_ELEMENT_OF: "∉" >
 |   < CROSSING: "⧉" >
 |   < PERCENT: "%" >
 |   < COMMENT_START: "/*" > : COMMENT
@@ -690,6 +691,8 @@ Selector child_selector() :
             |
                 <ELEMENT_OF> { type = Selector.ChildOrParentSelectorType.ELEMENT_OF; }
             |
+                <NOT_ELEMENT_OF> { type = Selector.ChildOrParentSelectorType.NOT_ELEMENT_OF; }
+            |
                 <CROSSING> { type = Selector.ChildOrParentSelectorType.CROSSING; }
             )
             w()
diff --git src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
index 30f0007a8..3edcc7d95 100644
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
@@ -93,7 +93,7 @@ public interface Selector {
      * @see ChildOrParentSelector
      */
     enum ChildOrParentSelectorType {
-        CHILD, PARENT, ELEMENT_OF, CROSSING, SIBLING
+        CHILD, PARENT, ELEMENT_OF, NOT_ELEMENT_OF, CROSSING, SIBLING
     }
 
     /**
@@ -312,12 +312,35 @@ public interface Selector {
 
         @Override
         public boolean matches(Environment e) {
+            if (ChildOrParentSelectorType.ELEMENT_OF == type ||
+                    ChildOrParentSelectorType.NOT_ELEMENT_OF == type) {
+                if (!left.matches(e))
+                    return false;
+                boolean is_element_of = false;
+                // Does exist any element in dataset that contains e.osm?
+                for (IPrimitive p: e.osm.getDataSet().allPrimitives()) {
+                    Environment ne = new Environment(p);
+                    if (!right.matches(ne))
+                        continue;
+                    ContainsFinder cf = new ContainsFinder(ne);
+                    if (e.osm instanceof IWay)
+                        cf.visit((IWay) e.osm);
+                    if (e.osm instanceof INode)
+                        cf.visit((INode) e.osm);
+                    if (ne.child == e.osm)
+                        is_element_of = true;
+                }
+                if (ChildOrParentSelectorType.ELEMENT_OF == type)
+                    return is_element_of;
+                else
+                    return !is_element_of;
+            }
 
             if (!right.matches(e))
                 return false;
 
             if (ChildOrParentSelectorType.ELEMENT_OF == type) {
-
+/*
                 if (e.osm instanceof INode || e.osm.getDataSet() == null) {
                     // nodes cannot contain elements
                     return false;
@@ -362,7 +385,7 @@ public interface Selector {
                 }
 
                 return e.child != null;
-
+*/
             } else if (ChildOrParentSelectorType.CROSSING == type && e.osm instanceof IWay) {
                 e.parent = e.osm;
                 final CrossingFinder crossingFinder = new CrossingFinder(e);
-- 
2.11.0

