Index: applications/editors/josm/plugins/validator/ignoretags.cfg
===================================================================
--- applications/editors/josm/plugins/validator/ignoretags.cfg	(revision 16319)
+++ applications/editors/josm/plugins/validator/ignoretags.cfg	(revision 16319)
@@ -0,0 +1,125 @@
+# JOSM IgnoreTags
+;
+; Ignore valid and semi-valid keys that start with...
+;
+S:opengeodb
+S:openGeoDB
+S:name:
+S:note:
+S:tiger:
+S:gnis:
+S:census:
+S:au.gov.abs:
+S:qroti:
+S:is_in:
+S:wikipedia
+;
+; Ignore valid and semi-valid keys that equal...
+;
+E:loc_name
+E:attribution
+E:admin_level
+E:old_name
+E:usage
+E:construction
+E:collection
+E:addr:state
+E:import_uuid
+E:url
+E:postal_code
+;
+; Ignore valid and semi-valid keys that end with...
+;
+F::nswgnb
+F::forward
+F::backward
+F::left
+F::right
+;
+; Highway Key/Value Pairs
+;
+K:highway=secondary_link
+;
+; Aeroway Key/Value Pairs
+;
+K:aeroway=taxiway
+K:aeroway=runway
+K:aeroway=terminal
+K:aeroway=hanger
+;
+; Amenity Key/Value Pairs
+;
+K:amenity=bbq
+;
+; Surface Key/Value Pairs
+;
+K:surface=dirt
+K:surface=wood
+;
+; Religious Key/Value Pairs
+;
+T:religion=muslim|denomination=alaouite
+T:religion=jewish|denomination=alternative
+T:religion=jewish|denomination=ashkenazi
+T:religion=christian|denomination=catholic
+T:religion=christian|denomination=christian_community
+T:religion=christian|denomination=christian_science
+T:religion=jewish|denomination=conservative
+T:religion=christian|denomination=coptic_orthodox
+T:religion=christian|denomination=czechoslovak_hussite
+T:religion=muslim|denomination=druze
+T:religion=christian|denomination=dutch_reformed
+T:religion=christian|denomination=evangelical
+T:religion=pastafarian|denomination=EVKdFSMiD
+T:religion=christian|denomination=foursquare
+T:religion=christian|denomination=greek_orthodox
+T:religion=jewish|denomination=hasidic
+T:religion=jewish|denomination=humanistic  
+T:religion=muslim|denomination=ibadi
+T:religion=muslim|denomination=ismaili
+T:religion=christian|denomination=jehovahs_witness
+T:religion=christian|denomination=kabbalah
+T:religion=christian|denomination=karaite  
+T:religion=jewish|denomination=liberal  
+T:religion=christian|denomination=living_waters_church
+T:religion=christian|denomination=lutheran
+T:religion=christian|denomination=maronite
+T:religion=christian|denomination=mennonite
+T:religion=christian|denomination=methodist
+T:religion=jewish|denomination=modern_orthodox
+T:religion=christian|denomination=mormon
+T:religion=jewish|denomination=neo_orthodox
+T:religion=christian|denomination=new_apostolic
+T:religion=christian|denomination=nondenominational
+T:religion=jewish|denomination=nondenominational
+T:religion=muslim|denomination=nondenominational
+T:religion=christian|denomination=old_catholic
+T:religion=christian|denomination=orthodox 
+T:religion=jewish|denomination=orthodox 
+T:religion=christian|denomination=pentecostal
+T:religion=christian|denomination=presbyterian
+T:religion=jewish|denomination=progressive 
+T:religion=christian|denomination=protestant
+T:religion=christian|denomination=quaker
+T:religion=jewish|denomination=reconstructionist
+T:religion=jewish|denomination=reform
+T:religion=jewish|denomination=renewal   
+T:religion=christian|denomination=roman_catholic
+T:religion=christian|denomination=russian_orthodox
+T:religion=christian|denomination=salvation_army
+T:religion=jewish|denomination=samaritan
+T:religion=christian|denomination=seventh_day_adventist
+T:religion=muslim|denomination=shia
+T:religion=muslim|denomination=sunni  
+T:religion=jewish|denomination=ultra_orthodox
+T:religion=christian|denomination=united
+T:religion=christian|denomination=united_reformed
+T:religion=christian|denomination=uniting
+;
+; Shop Key/Value Pairs
+;
+K:shop=mall
+;
+; Type Key/Value Pairs
+;
+K:type=collection
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java	(revision 16318)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/TagChecker.java	(revision 16319)
@@ -66,4 +66,5 @@
     /** The default data files */
     public static final String DATA_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/tagchecker.cfg";
+    public static final String IGNORE_FILE = "http://svn.openstreetmap.org/applications/editors/josm/plugins/validator/ignoretags.cfg";
     public static final String SPELL_FILE = "http://svn.openstreetmap.org/applications/utils/planet.osm/java/speller/words.cfg";
 
@@ -74,4 +75,8 @@
     /** The TagChecker data */
     protected static List<CheckerData> checkerData = new ArrayList<CheckerData>();
+    protected static ArrayList<String> ignoreDataStartsWith = new ArrayList<String>();
+    protected static ArrayList<String> ignoreDataEquals = new ArrayList<String>();
+    protected static ArrayList<String> ignoreDataEndsWith = new ArrayList<String>();
+    protected static ArrayList<IgnoreKeyPair> ignoreDataKeyPair = new ArrayList<IgnoreKeyPair>();
 
     /** The preferences prefix */
@@ -86,4 +91,5 @@
     public static final String PREF_SOURCES = PREFIX + ".sources";
     public static final String PREF_USE_DATA_FILE = PREFIX + ".usedatafile";
+    public static final String PREF_USE_IGNORE_FILE = PREFIX + ".useignorefile";
     public static final String PREF_USE_SPELL_FILE = PREFIX + ".usespellfile";
 
@@ -113,4 +119,5 @@
 
     protected JCheckBox prefUseDataFile;
+    protected JCheckBox prefUseIgnoreFile;
     protected JCheckBox prefUseSpellFile;
 
@@ -169,4 +176,11 @@
                 sources = DATA_FILE + ";" + sources;
         }
+        if(Main.pref.getBoolean(PREF_USE_IGNORE_FILE, true))
+        {
+            if( sources == null || sources.length() == 0)
+                sources = IGNORE_FILE;
+            else
+                sources = IGNORE_FILE + ";" + sources;
+        }
         if(Main.pref.getBoolean(PREF_USE_SPELL_FILE, true))
         {
@@ -198,4 +212,5 @@
                 String okValue = null;
                 Boolean tagcheckerfile = false;
+                Boolean ignorefile = false;
                 String line;
                 while((line = reader.readLine()) != null && (tagcheckerfile || line.length() != 0))
@@ -205,4 +220,38 @@
                         if(line.startsWith("# JOSM TagChecker"))
                             tagcheckerfile = true;
+                        if(line.startsWith("# JOSM IgnoreTags"))
+                            ignorefile = true;
+                        continue;
+                    }
+                    else if(ignorefile)
+                    {
+                        line = line.trim();
+                        if(line.length() < 4)
+                            continue;
+
+                        String key = line.substring(0, 2);
+                        line = line.substring(2);
+
+                        if(key.equals("S:"))
+                        {
+                            ignoreDataStartsWith.add(line);
+                        }
+                        else if(key.equals("E:"))
+                        {
+                            ignoreDataEquals.add(line);
+                        }
+                        else if(key.equals("F:"))
+                        {
+                            ignoreDataEndsWith.add(line);
+                        }
+                        else if(key.equals("K:"))
+                        {
+                            IgnoreKeyPair tmp = new IgnoreKeyPair();
+                            int mid = line.indexOf("=");
+                            tmp.key = line.substring(0, mid);
+                            tmp.value = line.substring(mid+1);
+                            ignoreDataKeyPair.add(tmp);
+                        }
+                        continue;
                     }
                     else if(tagcheckerfile)
@@ -391,12 +440,15 @@
                 {
                     Boolean ignore = false;
-                    for(String a : Main.pref.getCollection(PreferenceEditor.PREFIX + ".startswithkeys",
-                    Arrays.asList(new String[]{"opengeodb","openGeoDB","name:","note:"})))
+                    for(String a : ignoreDataStartsWith)
                     {
                         if(key.startsWith(a))
                             ignore = true;
                     }
-                    for(String a : Main.pref.getCollection(PreferenceEditor.PREFIX + ".endswithkeys",
-                    Arrays.asList(new String[]{":forward",":backward",":left",":right"})))
+                    for(String a : ignoreDataEquals)
+                    {
+                        if(key.equals(a))
+                            ignore = true;
+                    }
+                    for(String a : ignoreDataEndsWith)
                     {
                         if(key.endsWith(a))
@@ -413,8 +465,18 @@
                 else if(values.size() > 0 && !values.contains(prop.getValue()))
                 {
-                    String i = marktr("Value ''{0}'' for key ''{1}'' not in presets.");
-                    errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property value"),
-                    tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p) );
-                    withErrors.add(p, "UPV");
+                    boolean ignore = false;
+                    for(IgnoreKeyPair a : ignoreDataKeyPair)
+                    {
+                        if(key.equals(a.key) && value.equals(a.value))
+                            ignore = true;
+                    }
+
+                    if(!ignore)
+                    {
+                        String i = marktr("Value ''{0}'' for key ''{1}'' not in presets.");
+                        errors.add( new TestError(this, Severity.OTHER, tr("Presets do not contain property value"),
+                        tr(i, prop.getValue(), key), MessageFormat.format(i, prop.getValue(), key), INVALID_VALUE, p) );
+                        withErrors.add(p, "UPV");
+                    }
                 }
             }
@@ -601,4 +663,8 @@
         prefUseDataFile.setToolTipText(tr("Use the default data file (recommended)."));
         testPanel.add(prefUseDataFile, GBC.eol().insets(20,0,0,0));
+
+        prefUseIgnoreFile = new JCheckBox(tr("Use default tag ignore file."), Main.pref.getBoolean(PREF_USE_IGNORE_FILE, true));
+        prefUseIgnoreFile.setToolTipText(tr("Use the default tag ignore file (recommended)."));
+        testPanel.add(prefUseIgnoreFile, GBC.eol().insets(20,0,0,0));
 
         prefUseSpellFile = new JCheckBox(tr("Use default spellcheck file."), Main.pref.getBoolean(PREF_USE_SPELL_FILE, true));
@@ -635,4 +701,5 @@
         Main.pref.put(PREF_CHECK_PAINT_BEFORE_UPLOAD, prefCheckPaintBeforeUpload.isSelected());
         Main.pref.put(PREF_USE_DATA_FILE, prefUseDataFile.isSelected());
+        Main.pref.put(PREF_USE_IGNORE_FILE, prefUseIgnoreFile.isSelected());
         Main.pref.put(PREF_USE_SPELL_FILE, prefUseSpellFile.isSelected());
         String sources = "";
@@ -709,4 +776,9 @@
 
         return false;
+    }
+
+    private static class IgnoreKeyPair {
+        public String key;
+        public String value;
     }
 
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java	(revision 16318)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/UnconnectedWays.java	(revision 16319)
@@ -12,4 +12,5 @@
 
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmUtils;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.Main;
@@ -65,7 +66,10 @@
         for(Node en : endnodes_highway)
         {
+            if("turning_circle".equals(en.get("highway")) ||
+            OsmUtils.getOsmBoolean(en.get("noexit")) || en.get("barrier") != null)
+                continue;
             for(MyWaySegment s : ways)
             {
-                if(s.highway && s.nearby(en, mindist) && (a == null || a.contains(en.getCoor())))
+                if(!s.isBoundary && !s.isAbandoned && s.highway && s.nearby(en, mindist) && (a == null || a.contains(en.getCoor())))
                     map.put(en, s.w);
             }
@@ -85,5 +89,5 @@
             for(MyWaySegment s : ways)
             {
-                if(!s.highway && s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor())))
+                if(!s.isBoundary && !s.isAbandoned && !s.highway && s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor())))
                     map.put(en, s.w);
             }
@@ -93,5 +97,5 @@
             for(MyWaySegment s : ways)
             {
-                if(s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor())))
+                if(!s.isBoundary && !s.isAbandoned && s.nearby(en, mindist) && !s.isArea() && (a == null || a.contains(en.getCoor())))
                     map.put(en, s.w);
             }
@@ -114,5 +118,5 @@
                 for(MyWaySegment s : ways)
                 {
-                    if(s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor())))
+                    if(!s.isBoundary && !s.isAbandoned && s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor())))
                         map.put(en, s.w);
                 }
@@ -132,5 +136,5 @@
                 for(MyWaySegment s : ways)
                 {
-                    if(s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor())))
+                    if(!s.isBoundary && !s.isAbandoned && s.nearby(en, minmiddledist) && (a == null || a.contains(en.getCoor())))
                         map.put(en, s.w);
                 }
@@ -154,4 +158,6 @@
         private Line2D line;
         public Way w;
+        public Boolean isAbandoned = false;
+        public Boolean isBoundary = false;
         public Boolean highway;
 
@@ -159,5 +165,8 @@
         {
             this.w = w;
-            this.highway = w.get("highway") != null || w.get("railway") != null;
+            String railway = w.get("railway");
+            this.isAbandoned = railway != null && railway.equals("abandoned");
+            this.highway = w.get("highway") != null || (railway != null && !isAbandoned);
+            this.isBoundary = w.get("boundary") != null && w.get("boundary").equals("administrative") && !this.highway;
             line = new Line2D.Double(n1.getEastNorth().east(), n1.getEastNorth().north(),
             n2.getEastNorth().east(), n2.getEastNorth().north());
@@ -169,5 +178,5 @@
             && line.ptSegDist(n.getEastNorth().east(), n.getEastNorth().north()) < dist;
         }
-        
+
         public boolean isArea() {
             return w.get("landuse") != null
