From 3b1c413d92700aff04349e2fa0edd7cf85ec8289 Mon Sep 17 00:00:00 2001
From: Michael Zangl <michael.zangl@student.kit.edu>
Date: Sat, 8 Aug 2015 15:49:21 +0200
Subject: [PATCH] Made MapCSS use the visitor pattern to retrive tags of
 primitives.

---
 .../josm/data/osm/AbstractPrimitive.java           | 26 ++++++++++++++++++
 .../gui/mappaint/mapcss/MapCSSStyleSource.java     | 32 +++++++++++++++-------
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java b/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
index 2d30e5f..7276103 100644
--- a/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
+++ b/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
@@ -26,6 +26,19 @@ import org.openstreetmap.josm.tools.Utils;
 */
 public abstract class AbstractPrimitive implements IPrimitive {
 
+    /**
+     * This is a visitor that can be used to loop over the keys/values of this primitive.
+     * @author Michael Zangl
+     */
+    public interface KeyValueVisitor {
+        /**
+         * This method gets called for every tag recieved.
+         * @param key The key
+         * @param value The value
+         */
+        void visitKeyValue(String key, String value);
+    }
+
     private static final AtomicLong idCounter = new AtomicLong(0);
 
     static long generateUniqueId() {
@@ -495,6 +508,19 @@ public abstract class AbstractPrimitive implements IPrimitive {
     }
 
     /**
+     * Calls the visitor for every key/value pair of this primitive.
+     * @param visitor The visitor to call.
+     */
+    public void visitKeys(KeyValueVisitor visitor) {
+        final String[] keys = this.keys;
+        if (keys != null) {
+            for (int i = 0; i < keys.length; i += 2) {
+                visitor.visitKeyValue(keys[i], keys[i + 1]);
+            }
+        }
+    }
+
+    /**
      * Sets the keys of this primitives to the key/value pairs in <code>keys</code>.
      * Old key/value pairs are removed.
      * If <code>keys</code> is null, clears existing key/value pairs.
diff --git a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
index 49b2fc3..a97450b 100644
--- a/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
+++ b/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java
@@ -29,6 +29,7 @@ import java.util.zip.ZipFile;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Version;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive.KeyValueVisitor;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
@@ -144,13 +145,12 @@ public class MapCSSStyleSource extends StyleSource {
          *
          * @author Michael Zangl
          */
-        private final class RuleCandidatesIterator implements Iterator<MapCSSRule> {
+        private final class RuleCandidatesIterator implements Iterator<MapCSSRule>, KeyValueVisitor {
             private final BitSet ruleCandidates;
             private int next;
 
             private RuleCandidatesIterator(BitSet ruleCandidates) {
                 this.ruleCandidates = ruleCandidates;
-                next = ruleCandidates.nextSetBit(0);
             }
 
             @Override
@@ -169,6 +169,22 @@ public class MapCSSStyleSource extends StyleSource {
             public void remove() {
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public void visitKeyValue(String key, String value) {
+                MapCSSKeyRules v = index.get(key);
+                if (v != null) {
+                    BitSet rs = v.get(value);
+                    ruleCandidates.or(rs);
+                }
+            }
+
+            /**
+             * Call this before using the iterator.
+             */
+            public void prepare() {
+                next = ruleCandidates.nextSetBit(0);
+            }
         }
 
         /**
@@ -317,14 +333,10 @@ public class MapCSSStyleSource extends StyleSource {
             final BitSet ruleCandidates = new BitSet(rules.size());
             ruleCandidates.or(remaining);
 
-            for (Map.Entry<String, String> e : osm.getKeys().entrySet()) {
-                MapCSSKeyRules v = index.get(e.getKey());
-                if (v != null) {
-                    BitSet rs = v.get(e.getValue());
-                    ruleCandidates.or(rs);
-                }
-            }
-            return new RuleCandidatesIterator(ruleCandidates);
+            RuleCandidatesIterator res = new RuleCandidatesIterator(ruleCandidates);
+            osm.visitKeys(res);
+            res.prepare();
+            return res;
         }
 
         /**
-- 
1.9.1

