Index: trunk/src/org/openstreetmap/josm/actions/upload/DiscardTagsHook.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/upload/DiscardTagsHook.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/actions/upload/DiscardTagsHook.java	(revision 13809)
@@ -13,4 +13,5 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.APIDataSet;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -24,5 +25,5 @@
     public boolean checkUpload(APIDataSet apiDataSet) {
         List<OsmPrimitive> objectsToUpload = apiDataSet.getPrimitives();
-        Collection<String> discardableKeys = new HashSet<>(OsmPrimitive.getDiscardableKeys());
+        Collection<String> discardableKeys = new HashSet<>(AbstractPrimitive.getDiscardableKeys());
 
         boolean needsChange = false;
Index: trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
===================================================================
--- trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java	(revision 13809)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.data.correction.RoleCorrection;
 import org.openstreetmap.josm.data.correction.TagCorrection;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -55,5 +56,5 @@
     private static final Collection<Pattern> IGNORED_KEYS = new ArrayList<>();
     static {
-        for (String s : OsmPrimitive.getUninterestingKeys()) {
+        for (String s : AbstractPrimitive.getUninterestingKeys()) {
             IGNORED_KEYS.add(getPatternFor(s));
         }
Index: trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java	(revision 13809)
@@ -9,5 +9,8 @@
 import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -16,4 +19,5 @@
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.LanguageInfo;
 import org.openstreetmap.josm.tools.Utils;
@@ -742,3 +746,136 @@
         return getName();
     }
+
+    /*-------------------------------------
+     * WORK IN PROGRESS, UNINTERESTING KEYS
+     *-------------------------------------*/
+
+    private static volatile Collection<String> workinprogress;
+    private static volatile Collection<String> uninteresting;
+    private static volatile Collection<String> discardable;
+
+    /**
+     * Returns a list of "uninteresting" keys that do not make an object
+     * "tagged".  Entries that end with ':' are causing a whole namespace to be considered
+     * "uninteresting".  Only the first level namespace is considered.
+     * Initialized by isUninterestingKey()
+     * @return The list of uninteresting keys.
+     */
+    public static Collection<String> getUninterestingKeys() {
+        if (uninteresting == null) {
+            List<String> l = new LinkedList<>(Arrays.asList(
+                "source", "source_ref", "source:", "comment",
+                "watch", "watch:", "description", "attribution"));
+            l.addAll(getDiscardableKeys());
+            l.addAll(getWorkInProgressKeys());
+            uninteresting = new HashSet<>(Config.getPref().getList("tags.uninteresting", l));
+        }
+        return uninteresting;
+    }
+
+    /**
+     * Returns a list of keys which have been deemed uninteresting to the point
+     * that they can be silently removed from data which is being edited.
+     * @return The list of discardable keys.
+     */
+    public static Collection<String> getDiscardableKeys() {
+        if (discardable == null) {
+            discardable = new HashSet<>(Config.getPref().getList("tags.discardable",
+                    Arrays.asList(
+                            "created_by",
+                            "converted_by",
+                            "geobase:datasetName",
+                            "geobase:uuid",
+                            "KSJ2:ADS",
+                            "KSJ2:ARE",
+                            "KSJ2:AdminArea",
+                            "KSJ2:COP_label",
+                            "KSJ2:DFD",
+                            "KSJ2:INT",
+                            "KSJ2:INT_label",
+                            "KSJ2:LOC",
+                            "KSJ2:LPN",
+                            "KSJ2:OPC",
+                            "KSJ2:PubFacAdmin",
+                            "KSJ2:RAC",
+                            "KSJ2:RAC_label",
+                            "KSJ2:RIC",
+                            "KSJ2:RIN",
+                            "KSJ2:WSC",
+                            "KSJ2:coordinate",
+                            "KSJ2:curve_id",
+                            "KSJ2:curve_type",
+                            "KSJ2:filename",
+                            "KSJ2:lake_id",
+                            "KSJ2:lat",
+                            "KSJ2:long",
+                            "KSJ2:river_id",
+                            "odbl",
+                            "odbl:note",
+                            "SK53_bulk:load",
+                            "sub_sea:type",
+                            "tiger:source",
+                            "tiger:separated",
+                            "tiger:tlid",
+                            "tiger:upload_uuid",
+                            "yh:LINE_NAME",
+                            "yh:LINE_NUM",
+                            "yh:STRUCTURE",
+                            "yh:TOTYUMONO",
+                            "yh:TYPE",
+                            "yh:WIDTH",
+                            "yh:WIDTH_RANK"
+                        )));
+        }
+        return discardable;
+    }
+
+    /**
+     * Returns a list of "work in progress" keys that do not make an object
+     * "tagged" but "annotated".
+     * @return The list of work in progress keys.
+     * @since 5754
+     */
+    public static Collection<String> getWorkInProgressKeys() {
+        if (workinprogress == null) {
+            workinprogress = new HashSet<>(Config.getPref().getList("tags.workinprogress",
+                    Arrays.asList("note", "fixme", "FIXME")));
+        }
+        return workinprogress;
+    }
+
+    /**
+     * Determines if key is considered "uninteresting".
+     * @param key The key to check
+     * @return true if key is considered "uninteresting".
+     */
+    public static boolean isUninterestingKey(String key) {
+        getUninterestingKeys();
+        if (uninteresting.contains(key))
+            return true;
+        int pos = key.indexOf(':');
+        if (pos > 0)
+            return uninteresting.contains(key.substring(0, pos + 1));
+        return false;
+    }
+
+    @Override
+    public Map<String, String> getInterestingTags() {
+        Map<String, String> result = new HashMap<>();
+        String[] keys = this.keys;
+        if (keys != null) {
+            for (int i = 0; i < keys.length; i += 2) {
+                if (!isUninterestingKey(keys[i])) {
+                    result.put(keys[i], keys[i + 1]);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public boolean hasSameInterestingTags(IPrimitive other) {
+        return (!hasKeys() && !other.hasKeys())
+                || getInterestingTags().equals(other.getInterestingTags());
+    }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/osm/IPrimitive.java	(revision 13809)
@@ -4,4 +4,5 @@
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 import org.openstreetmap.josm.data.osm.visitor.PrimitiveVisitor;
@@ -440,5 +441,22 @@
      * Returns the parent data set of this primitive.
      * @return OsmData this primitive is part of.
+     * @since 13807
      */
     OsmData<?, ?, ?, ?> getDataSet();
+
+    /**
+     * Returns {@link #getKeys()} for which {@code key} does not fulfill uninteresting criteria.
+     * @return A map of interesting tags
+     * @since 13809
+     */
+    Map<String, String> getInterestingTags();
+
+    /**
+     * Replies true if other isn't null and has the same interesting tags (key/value-pairs) as this.
+     *
+     * @param other the other object primitive
+     * @return true if other isn't null and has the same interesting tags (key/value-pairs) as this.
+     * @since 13809
+     */
+    boolean hasSameInterestingTags(IPrimitive other);
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 13809)
@@ -6,9 +6,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -608,133 +606,7 @@
     }
 
-    /*---------------------------------------------------
-     * WORK IN PROGRESS, UNINTERESTING AND DIRECTION KEYS
-     *--------------------------------------------------*/
-
-    private static volatile Collection<String> workinprogress;
-    private static volatile Collection<String> uninteresting;
-    private static volatile Collection<String> discardable;
-
-    /**
-     * Returns a list of "uninteresting" keys that do not make an object
-     * "tagged".  Entries that end with ':' are causing a whole namespace to be considered
-     * "uninteresting".  Only the first level namespace is considered.
-     * Initialized by isUninterestingKey()
-     * @return The list of uninteresting keys.
-     */
-    public static Collection<String> getUninterestingKeys() {
-        if (uninteresting == null) {
-            List<String> l = new LinkedList<>(Arrays.asList(
-                "source", "source_ref", "source:", "comment",
-                "watch", "watch:", "description", "attribution"));
-            l.addAll(getDiscardableKeys());
-            l.addAll(getWorkInProgressKeys());
-            uninteresting = new HashSet<>(Config.getPref().getList("tags.uninteresting", l));
-        }
-        return uninteresting;
-    }
-
-    /**
-     * Returns a list of keys which have been deemed uninteresting to the point
-     * that they can be silently removed from data which is being edited.
-     * @return The list of discardable keys.
-     */
-    public static Collection<String> getDiscardableKeys() {
-        if (discardable == null) {
-            discardable = new HashSet<>(Config.getPref().getList("tags.discardable",
-                    Arrays.asList(
-                            "created_by",
-                            "converted_by",
-                            "geobase:datasetName",
-                            "geobase:uuid",
-                            "KSJ2:ADS",
-                            "KSJ2:ARE",
-                            "KSJ2:AdminArea",
-                            "KSJ2:COP_label",
-                            "KSJ2:DFD",
-                            "KSJ2:INT",
-                            "KSJ2:INT_label",
-                            "KSJ2:LOC",
-                            "KSJ2:LPN",
-                            "KSJ2:OPC",
-                            "KSJ2:PubFacAdmin",
-                            "KSJ2:RAC",
-                            "KSJ2:RAC_label",
-                            "KSJ2:RIC",
-                            "KSJ2:RIN",
-                            "KSJ2:WSC",
-                            "KSJ2:coordinate",
-                            "KSJ2:curve_id",
-                            "KSJ2:curve_type",
-                            "KSJ2:filename",
-                            "KSJ2:lake_id",
-                            "KSJ2:lat",
-                            "KSJ2:long",
-                            "KSJ2:river_id",
-                            "odbl",
-                            "odbl:note",
-                            "SK53_bulk:load",
-                            "sub_sea:type",
-                            "tiger:source",
-                            "tiger:separated",
-                            "tiger:tlid",
-                            "tiger:upload_uuid",
-                            "yh:LINE_NAME",
-                            "yh:LINE_NUM",
-                            "yh:STRUCTURE",
-                            "yh:TOTYUMONO",
-                            "yh:TYPE",
-                            "yh:WIDTH",
-                            "yh:WIDTH_RANK"
-                        )));
-        }
-        return discardable;
-    }
-
-    /**
-     * Returns a list of "work in progress" keys that do not make an object
-     * "tagged" but "annotated".
-     * @return The list of work in progress keys.
-     * @since 5754
-     */
-    public static Collection<String> getWorkInProgressKeys() {
-        if (workinprogress == null) {
-            workinprogress = new HashSet<>(Config.getPref().getList("tags.workinprogress",
-                    Arrays.asList("note", "fixme", "FIXME")));
-        }
-        return workinprogress;
-    }
-
-    /**
-     * Determines if key is considered "uninteresting".
-     * @param key The key to check
-     * @return true if key is considered "uninteresting".
-     */
-    public static boolean isUninterestingKey(String key) {
-        getUninterestingKeys();
-        if (uninteresting.contains(key))
-            return true;
-        int pos = key.indexOf(':');
-        if (pos > 0)
-            return uninteresting.contains(key.substring(0, pos + 1));
-        return false;
-    }
-
-    /**
-     * Returns {@link #getKeys()} for which {@code key} does not fulfill {@link #isUninterestingKey}.
-     * @return A map of interesting tags
-     */
-    public Map<String, String> getInterestingTags() {
-        Map<String, String> result = new HashMap<>();
-        String[] keys = this.keys;
-        if (keys != null) {
-            for (int i = 0; i < keys.length; i += 2) {
-                if (!isUninterestingKey(keys[i])) {
-                    result.put(keys[i], keys[i + 1]);
-                }
-            }
-        }
-        return result;
-    }
+    /*---------------
+     * DIRECTION KEYS
+     *---------------*/
 
     private static Match compileDirectionKeys(String prefName, String defaultValue) throws AssertionError {
@@ -1097,15 +969,4 @@
 
     /**
-     * Replies true if other isn't null and has the same interesting tags (key/value-pairs) as this.
-     *
-     * @param other the other object primitive
-     * @return true if other isn't null and has the same interesting tags (key/value-pairs) as this.
-     */
-    public boolean hasSameInterestingTags(OsmPrimitive other) {
-        return (keys == null && other.keys == null)
-                || getInterestingTags().equals(other.getInterestingTags());
-    }
-
-    /**
      * Replies true if this primitive and other are equal with respect to their semantic attributes.
      * <ol>
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateRelation.java	(revision 13809)
@@ -18,4 +18,5 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -181,5 +182,5 @@
 
     /** List of keys without useful information */
-    private final Set<String> ignoreKeys = new HashSet<>(OsmPrimitive.getUninterestingKeys());
+    private final Set<String> ignoreKeys = new HashSet<>(AbstractPrimitive.getUninterestingKeys());
 
     /**
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateWay.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateWay.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/DuplicateWay.java	(revision 13809)
@@ -19,4 +19,5 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -170,5 +171,5 @@
      */
     public void removeUninterestingKeys(Map<String, String> wkeys) {
-        for (String key : OsmPrimitive.getDiscardableKeys()) {
+        for (String key : AbstractPrimitive.getDiscardableKeys()) {
             wkeys.remove(key);
         }
Index: trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/TagChecker.java	(revision 13809)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
@@ -289,5 +290,5 @@
         if (!presets.isEmpty()) {
             additionalPresetsValueData = new MultiMap<>();
-            for (String a : OsmPrimitive.getUninterestingKeys()) {
+            for (String a : AbstractPrimitive.getUninterestingKeys()) {
                 additionalPresetsValueData.putVoid(a);
             }
Index: trunk/src/org/openstreetmap/josm/gui/conflict/tags/CombinePrimitiveResolver.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/conflict/tags/CombinePrimitiveResolver.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/gui/conflict/tags/CombinePrimitiveResolver.java	(revision 13809)
@@ -7,4 +7,5 @@
 import org.openstreetmap.josm.command.ChangePropertyCommand;
 import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.TagCollection;
@@ -41,5 +42,5 @@
             cmds.addAll(buildTagChangeCommand(targetPrimitive, allResolutions));
         }
-        for (String p : OsmPrimitive.getDiscardableKeys()) {
+        for (String p : AbstractPrimitive.getDiscardableKeys()) {
             if (targetPrimitive.get(p) != null) {
                 cmds.add(new ChangePropertyCommand(targetPrimitive, p, null));
Index: trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagConflictResolutionUtil.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagConflictResolutionUtil.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/gui/conflict/tags/TagConflictResolutionUtil.java	(revision 13809)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.data.StructUtils;
 import org.openstreetmap.josm.data.StructUtils.StructEntry;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Tag;
@@ -101,5 +102,5 @@
         // remove irrelevant tags
         //
-        for (String key : OsmPrimitive.getDiscardableKeys()) {
+        for (String key : AbstractPrimitive.getDiscardableKeys()) {
             tc.removeByKey(key);
         }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesCellRenderer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesCellRenderer.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesCellRenderer.java	(revision 13809)
@@ -21,5 +21,5 @@
 import javax.swing.table.TableCellRenderer;
 
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.data.preferences.CachingProperty;
@@ -52,5 +52,5 @@
     private static void setColors(Component c, String key, boolean isSelected) {
 
-        if (OsmPrimitive.getDiscardableKeys().contains(key)) {
+        if (AbstractPrimitive.getDiscardableKeys().contains(key)) {
             c.setForeground((isSelected ? SELECTED_FG : NORMAL_FG).get());
             c.setBackground((isSelected ? SELECTED_BG : NORMAL_BG).get());
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 13808)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/properties/PropertiesDialog.java	(revision 13809)
@@ -60,4 +60,5 @@
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
@@ -580,5 +581,5 @@
             types.add(TaggingPresetType.forPrimitive(osm));
             for (String key : osm.keySet()) {
-                if (displayDiscardableKeys || !OsmPrimitive.getDiscardableKeys().contains(key)) {
+                if (displayDiscardableKeys || !AbstractPrimitive.getDiscardableKeys().contains(key)) {
                     String value = osm.get(key);
                     keyCount.put(key, keyCount.containsKey(key) ? keyCount.get(key) + 1 : 1);
