Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 20335)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/TestError.java	(revision 20365)
@@ -239,4 +239,5 @@
     }
 
+    @SuppressWarnings("unchecked")
     public void visitHighlighted(ValidatorVisitor v) {
         for (Object o : highlighted) {
@@ -245,4 +246,7 @@
             else if (o instanceof WaySegment)
                 v.visit((WaySegment) o);
+            else if (o instanceof List<?>) {
+                v.visit((List<Node>)o);
+            }
         }
     }
@@ -288,13 +292,5 @@
         }
 
-        /**
-         * Draws a line around the segment
-         *
-         * @param s The segment
-         * @param color The color
-         */
-        public void drawSegment(Node n1, Node n2, Color color) {
-            Point p1 = mv.getPoint(n1);
-            Point p2 = mv.getPoint(n2);
+        public void drawSegment(Point p1, Point p2, Color color) {
             g.setColor(color);
 
@@ -322,4 +318,14 @@
 
         /**
+         * Draws a line around the segment
+         *
+         * @param s The segment
+         * @param color The color
+         */
+        public void drawSegment(Node n1, Node n2, Color color) {
+            drawSegment(mv.getPoint(n1), mv.getPoint(n2), color);
+        }
+
+        /**
          * Draw a small rectangle.
          * White if selected (as always) or red otherwise.
@@ -333,15 +339,5 @@
 
         public void visit(Way w) {
-            Node lastN = null;
-            for (Node n : w.getNodes()) {
-                if (lastN == null) {
-                    lastN = n;
-                    continue;
-                }
-                if (isSegmentVisible(lastN, n)) {
-                    drawSegment(lastN, n, severity.getColor());
-                }
-                lastN = n;
-            }
+            visit(w.getNodes());
         }
 
@@ -389,4 +385,18 @@
             return true;
         }
+
+        public void visit(List<Node> nodes) {
+            Node lastN = null;
+            for (Node n : nodes) {
+                if (lastN == null) {
+                    lastN = n;
+                    continue;
+                }
+                if (n.isDrawable() && isSegmentVisible(lastN, n)) {
+                    drawSegment(lastN, n, severity.getColor());
+                }
+                lastN = n;
+            }
+        }
     }
 
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 20335)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorDialog.java	(revision 20365)
@@ -18,4 +18,5 @@
 import java.util.HashSet;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Set;
 
@@ -35,4 +36,5 @@
 import org.openstreetmap.josm.data.SelectionChangedListener;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.WaySegment;
@@ -432,4 +434,10 @@
             visit(ws.way.getNodes().get(ws.lowerIndex));
             visit(ws.way.getNodes().get(ws.lowerIndex + 1));
+        }
+
+        public void visit(List<Node> nodes) {
+            for (Node n: nodes) {
+                visit(n);
+            }
         }
     }
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java	(revision 20335)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/ValidatorVisitor.java	(revision 20365)
@@ -1,4 +1,7 @@
 package org.openstreetmap.josm.plugins.validator;
 
+import java.util.List;
+
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.WaySegment;
@@ -6,5 +9,5 @@
 public interface ValidatorVisitor {
     void visit(OsmPrimitive p);
-
     void visit(WaySegment ws);
+    void visit(List<Node> nodes);
 }
Index: applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/MultipolygonTest.java
===================================================================
--- applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/MultipolygonTest.java	(revision 20335)
+++ applications/editors/josm/plugins/validator/src/org/openstreetmap/josm/plugins/validator/tests/MultipolygonTest.java	(revision 20365)
@@ -3,9 +3,17 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.geom.GeneralPath;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
+import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon;
-import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData;
+import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.JoinedWay;
 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon.PolyData.Intersection;
 import org.openstreetmap.josm.plugins.validator.Severity;
@@ -22,4 +30,6 @@
     protected static final int CROSSING_WAYS = 1606;
 
+    private final List<List<Node>> nonClosedWays = new ArrayList<List<Node>>();
+
     public MultipolygonTest() {
         super(tr("Multipolygon"),
@@ -27,6 +37,63 @@
     }
 
+    private List<List<Node>> joinWays(Collection<Way> ways) {
+        List<List<Node>> result = new ArrayList<List<Node>>();
+        List<Way> waysToJoin = new ArrayList<Way>();
+        for (Way way: ways) {
+            if (way.isClosed()) {
+                result.add(way.getNodes());
+            } else {
+                waysToJoin.add(way);
+            }
+        }
+
+        for (JoinedWay jw: Multipolygon.joinWays(waysToJoin)) {
+            if (!jw.isClosed()) {
+                nonClosedWays.add(jw.getNodes());
+            }
+            result.add(jw.getNodes());
+        }
+        return result;
+    }
+
+    private GeneralPath createPath(List<Node> nodes) {
+        GeneralPath result = new GeneralPath();
+        result.moveTo((float)nodes.get(0).getCoor().lat(), (float)nodes.get(0).getCoor().lon());
+        for (int i=1; i<nodes.size(); i++) {
+            Node n = nodes.get(i);
+            result.lineTo((float)n.getCoor().lat(), (float)n.getCoor().lon());
+        }
+        return result;
+    }
+
+    private List<GeneralPath> createPolygons(List<List<Node>> joinedWays) {
+        List<GeneralPath> result = new ArrayList<GeneralPath>();
+        for (List<Node> way: joinedWays) {
+            if (way.size() >= 3) {
+                result.add(createPath(way));
+            }
+        }
+        return result;
+    }
+
+    private Intersection getPolygonIntersection(GeneralPath outer, List<Node> inner) {
+        boolean inside = false;
+        boolean outside = false;
+
+        for (Node n: inner) {
+            boolean contains = outer.contains(n.getCoor().lat(), n.getCoor().lon());
+            inside = inside | contains;
+            outside = outside | !contains;
+            if (inside & outside) {
+                return Intersection.CROSSING;
+            }
+        }
+
+        return inside?Intersection.INSIDE:Intersection.OUTSIDE;
+    }
+
     @Override
     public void visit(Relation r) {
+        nonClosedWays.clear();
         if ("multipolygon".equals(r.get("type"))) {
             checkMembersAndRoles(r);
@@ -34,8 +101,4 @@
             Multipolygon polygon = new Multipolygon(Main.map.mapView);
             polygon.load(r);
-
-            if (polygon.hasNonClosedWays()) {
-                errors.add( new TestError(this, Severity.WARNING, tr("Multipolygon is not closed"), NON_CLOSED_WAY,  r));
-            }
 
             if (polygon.getOuterWays().isEmpty()) {
@@ -49,10 +112,35 @@
             }
 
-            for (PolyData pdInner: polygon.getInnerPolygons()) {
-                PolyData pdOuter = polygon.findOuterPolygon(pdInner, polygon.getOuterPolygons());
-                if (pdOuter == null) {
-                    errors.add(new TestError(this, Severity.WARNING, tr("Multipolygon inner way is outside."), INNER_WAY_OUTSIDE,  r));
-                } else if (pdOuter.contains(pdInner.poly) == Intersection.CROSSING) {
-                    errors.add(new TestError(this, Severity.WARNING, tr("Intersection between multipolygon ways"), CROSSING_WAYS, r));
+            List<List<Node>> innerWays = joinWays(polygon.getInnerWays()); // Side effect - sets nonClosedWays
+            List<List<Node>> outerWays = joinWays(polygon.getOuterWays());
+
+            if (!nonClosedWays.isEmpty()) {
+                errors.add( new TestError(this, Severity.WARNING, tr("Multipolygon is not closed"), NON_CLOSED_WAY,  Collections.singletonList(r), nonClosedWays));
+            }
+
+            // For painting is used Polygon class which works with ints only. For validation we need more precision
+            List<GeneralPath> outerPolygons = createPolygons(outerWays);
+            for (List<Node> pdInner: innerWays) {
+                boolean outside = true;
+                boolean crossing = false;
+                List<Node> outerWay = null;
+                for (int i=0; i<outerWays.size(); i++) {
+                    GeneralPath outer = outerPolygons.get(i);
+                    Intersection intersection = getPolygonIntersection(outer, pdInner);
+                    outside = outside & intersection == Intersection.OUTSIDE;
+                    if (intersection == Intersection.CROSSING) {
+                        crossing = true;
+                        outerWay = outerWays.get(i);
+                    }
+                }
+                if (outside | crossing) {
+                    List<List<Node>> highlights = new ArrayList<List<Node>>();
+                    highlights.add(pdInner);
+                    if (outside) {
+                        errors.add(new TestError(this, Severity.WARNING, tr("Multipolygon inner way is outside."), INNER_WAY_OUTSIDE, Collections.singletonList(r), highlights));
+                    } else if (crossing) {
+                        highlights.add(outerWay);
+                        errors.add(new TestError(this, Severity.WARNING, tr("Intersection between multipolygon ways"), CROSSING_WAYS, Collections.singletonList(r), highlights));
+                    }
                 }
             }
