Index: /trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java	(revision 4682)
@@ -5,4 +5,5 @@
 
 import java.text.MessageFormat;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -693,3 +694,22 @@
     }
 
+    /**
+     * Tests whether this primitive contains a tag consisting of {@code key} and any of {@code values}.
+     * @param key the key forming the tag.
+     * @param values one or many values forming the tag.
+     * @return true iff primitive contains a tag consisting of {@code key} and any of {@code values}.
+     */
+    public boolean hasTag(String key, String... values) {
+        return hasTag(key, Arrays.asList(values));
+    }
+
+    /**
+     * Tests whether this primitive contains a tag consisting of {@code key} and any of {@code values}.
+     * @param key the key forming the tag.
+     * @param values one or many values forming the tag.
+     * @return true iff primitive contains a tag consisting of {@code key} and any of {@code values}.
+     */
+    public boolean hasTag(String key, Collection<String> values) {
+        return values.contains(get(key));
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/data/osm/Way.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Way.java	(revision 4682)
@@ -448,4 +448,9 @@
     }
 
+    /**
+     * Returns the last node of this way.
+     * The result equals <tt>{@link #getNode getNode}({@link #getNodesCount getNodesCount} - 1)</tt>.
+     * @return the last node of this way
+     */
     public Node lastNode() {
         Node[] nodes = this.nodes;
@@ -454,4 +459,9 @@
     }
 
+    /**
+     * Returns the first node of this way.
+     * The result equals {@link #getNode getNode}{@code (0)}.
+     * @return the first node of this way
+     */
     public Node firstNode() {
         Node[] nodes = this.nodes;
Index: /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 4682)
@@ -48,4 +48,5 @@
 import org.openstreetmap.josm.data.validation.tests.UntaggedNode;
 import org.openstreetmap.josm.data.validation.tests.UntaggedWay;
+import org.openstreetmap.josm.data.validation.tests.WayConnectedToArea;
 import org.openstreetmap.josm.data.validation.tests.WronglyOrderedWays;
 import org.openstreetmap.josm.gui.MapView.LayerChangeListener;
@@ -102,4 +103,5 @@
         DeprecatedTags.class, // ID 2101 .. 2199
         OverlappingAreas.class, // ID 2201 .. 2299
+        WayConnectedToArea.class, // ID 2301 .. 2399
     };
 
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/MultipolygonTest.java	(revision 4682)
@@ -26,5 +26,4 @@
 import org.openstreetmap.josm.data.validation.TestError;
 import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
-import org.openstreetmap.josm.gui.mappaint.ElemStyle;
 import org.openstreetmap.josm.gui.mappaint.ElemStyles;
 import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
@@ -117,13 +116,8 @@
     @Override
     public void visit(Way w) {
-        if (styles != null && !w.isClosed()) {
-            for (ElemStyle s : styles.generateStyles(w, SCALE, null, false).a) {
-                if (s instanceof AreaElemStyle) {
-                    List<Node> nodes = w.getNodes();
-                    errors.add(new TestError(this, Severity.WARNING, tr("Area style way is not closed"), NOT_CLOSED, 
-                            Collections.singletonList(w), Arrays.asList(nodes.get(0), nodes.get(nodes.size() - 1))));
-                    break;
-                }
-            }
+        if (!w.isClosed() && ElemStyles.hasAreaElemStyle(w, false)) {
+            List<Node> nodes = w.getNodes();
+            errors.add(new TestError(this, Severity.WARNING, tr("Area style way is not closed"), NOT_CLOSED,
+                    Collections.singletonList(w), Arrays.asList(nodes.get(0), nodes.get(nodes.size() - 1))));
         }
     }
@@ -157,23 +151,10 @@
             if (styles != null) {
 
-                AreaElemStyle area = null;
-                boolean areaStyle = false;
-                for (ElemStyle s : styles.generateStyles(r, SCALE, null, false).a) {
-                    if (s instanceof AreaElemStyle) {
-                        area = (AreaElemStyle) s;
-                        areaStyle = true;
-                        break;
-                    }
-                }
+                AreaElemStyle area = ElemStyles.getAreaElemStyle(r, false);
+                boolean areaStyle = area != null;
                 // If area style was not found for relation then use style of ways
                 if (area == null) {
                     for (Way w : polygon.getOuterWays()) {
-
-                        for (ElemStyle s : styles.generateStyles(w, SCALE, null, true).a) {
-                            if (s instanceof AreaElemStyle) {
-                                area = (AreaElemStyle) s;
-                                break;
-                            }
-                        }
+                        area = ElemStyles.getAreaElemStyle(w, true);
                         if (area != null) {
                             break;
@@ -189,11 +170,5 @@
                 if (area != null) {
                     for (Way wInner : polygon.getInnerWays()) {
-                        AreaElemStyle areaInner = null;
-                        for (ElemStyle s : styles.generateStyles(wInner, SCALE, null, false).a) {
-                            if (s instanceof AreaElemStyle) {
-                                areaInner = (AreaElemStyle) s;
-                                break;
-                            }
-                        }
+                        AreaElemStyle areaInner = ElemStyles.getAreaElemStyle(wInner, false);
 
                         if (areaInner != null && area.equals(areaInner)) {
@@ -207,11 +182,5 @@
                     if(!areaStyle) {
                         for (Way wOuter : polygon.getOuterWays()) {
-                            AreaElemStyle areaOuter = null;
-                            for (ElemStyle s : styles.generateStyles(wOuter, SCALE, null, false).a) {
-                                if (s instanceof AreaElemStyle) {
-                                    areaOuter = (AreaElemStyle) s;
-                                    break;
-                                }
-                            }
+                            AreaElemStyle areaOuter = ElemStyles.getAreaElemStyle(wOuter, false);
                             if (areaOuter != null && !area.equals(areaOuter)) {
                                 List<OsmPrimitive> l = new ArrayList<OsmPrimitive>();
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingAreas.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingAreas.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/OverlappingAreas.java	(revision 4682)
@@ -5,5 +5,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.QuadBuckets;
 import org.openstreetmap.josm.data.osm.Way;
@@ -11,8 +10,5 @@
 import org.openstreetmap.josm.data.validation.Test;
 import org.openstreetmap.josm.data.validation.TestError;
-import org.openstreetmap.josm.gui.mappaint.AreaElemStyle;
-import org.openstreetmap.josm.gui.mappaint.ElemStyle;
 import org.openstreetmap.josm.gui.mappaint.ElemStyles;
-import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
 import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.Predicate;
@@ -23,5 +19,4 @@
     protected static int OVERLAPPING_AREAS = 2201;
     protected QuadBuckets<Way> index = new QuadBuckets<Way>();
-    private static ElemStyles styles = MapPaintStyles.getStyles();
 
     public OverlappingAreas() {
@@ -31,5 +26,5 @@
     @Override
     public void visit(Way w) {
-        if (w.isUsable() && w.isClosed() && hasAreaElemStyle(w)) {
+        if (w.isUsable() && w.isClosed() && ElemStyles.hasAreaElemStyle(w, false)) {
             index.add(w);
         }
@@ -60,11 +55,3 @@
     }
 
-    private boolean hasAreaElemStyle(OsmPrimitive p) {
-        for (ElemStyle s : styles.generateStyles(p, 1.0, null, false).a) {
-            if (s instanceof AreaElemStyle) {
-                return true;
-            }
-        }
-        return false;
-    }
 }
Index: /trunk/src/org/openstreetmap/josm/data/validation/tests/WayConnectedToArea.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/validation/tests/WayConnectedToArea.java	(revision 4682)
+++ /trunk/src/org/openstreetmap/josm/data/validation/tests/WayConnectedToArea.java	(revision 4682)
@@ -0,0 +1,57 @@
+package org.openstreetmap.josm.data.validation.tests;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.Arrays;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Relation;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.validation.Severity;
+import org.openstreetmap.josm.data.validation.Test;
+import org.openstreetmap.josm.data.validation.TestError;
+import org.openstreetmap.josm.gui.mappaint.ElemStyles;
+
+public class WayConnectedToArea extends Test {
+
+    public WayConnectedToArea() {
+        super(tr("Way connected to Area"));
+    }
+
+    @Override
+    public void visit(Way w) {
+        if (!w.isUsable() || w.isClosed() || !w.hasKey("highway")) {
+            return;
+        }
+
+        for (OsmPrimitive p : w.firstNode().getReferrers()) {
+            testForError(w, w.firstNode(), p);
+        }
+        for (OsmPrimitive p : w.lastNode().getReferrers()) {
+            testForError(w, w.lastNode(), p);
+        }
+
+    }
+
+    private void testForError(Way w, Node wayNode, OsmPrimitive p) {
+        if (ElemStyles.hasAreaElemStyle(p, false)) {
+            addError(w, wayNode, p);
+        } else {
+            for (OsmPrimitive r : p.getReferrers()) {
+                if (r instanceof Relation
+                        && r.hasTag("type", "multipolygon")
+                        && ElemStyles.hasAreaElemStyle(r, false)) {
+                    addError(w, wayNode, p);
+                    break;
+                }
+            }
+        }
+    }
+
+    private void addError(Way w, Node wayNode, OsmPrimitive p) {
+        errors.add(new TestError(this, Severity.WARNING,
+                tr("Way terminates on Area"), 2301,
+                Arrays.asList(w, p),
+                Arrays.asList(wayNode)));
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 4681)
+++ /trunk/src/org/openstreetmap/josm/gui/mappaint/ElemStyles.java	(revision 4682)
@@ -410,3 +410,35 @@
         styleSources.addAll(sources);
     }
+
+    /**
+     * Returns the first AreaElemStyle for a given primitive.
+     * @param p the OSM primitive
+     * @param pretendWayIsClosed For styles that require the way to be closed,
+     * we pretend it is. This is useful for generating area styles from the (segmented)
+     * outer ways of a multipolygon.
+     * @return first AreaElemStyle found or {@code null}.
+     */
+    public static AreaElemStyle getAreaElemStyle(OsmPrimitive p, boolean pretendWayIsClosed) {
+        if (MapPaintStyles.getStyles() == null) {
+            return null;
+        }
+        for (ElemStyle s : MapPaintStyles.getStyles().generateStyles(p, 1.0, null, pretendWayIsClosed).a) {
+            if (s instanceof AreaElemStyle) {
+                return (AreaElemStyle) s;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Determines whether primitive has an AreaElemStyle.
+     * @param p the OSM primitive
+     * @param pretendWayIsClosed For styles that require the way to be closed,
+     * we pretend it is. This is useful for generating area styles from the (segmented)
+     * outer ways of a multipolygon.
+     * @return {@code true} iff primitive has an AreaElemStyle
+     */
+    public static boolean hasAreaElemStyle(OsmPrimitive p, boolean pretendWayIsClosed) {
+        return getAreaElemStyle(p, pretendWayIsClosed) != null;
+    }
 }
