Index: trunk/src/org/openstreetmap/josm/data/validation/tests/BuildingInBuilding.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/tests/BuildingInBuilding.java	(revision 4746)
+++ trunk/src/org/openstreetmap/josm/data/validation/tests/BuildingInBuilding.java	(revision 4747)
@@ -10,5 +10,8 @@
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.data.osm.QuadBuckets;
+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.validation.Severity;
@@ -68,11 +71,6 @@
         //  |_______________________|
         //
-        for (int i=0; i<w.getNodesCount(); i++) {
-            LatLon center = null;
-            if (i > 0) {
-                center = w.getNode(i).getCoor().getCenter(w.getNode(i-1).getCoor());
-            } else if (w.isClosed()) {
-                center = w.getNode(i).getCoor().getCenter(w.getNode(w.getNodesCount()-2).getCoor());
-            }
+        for (int i=1; i<w.getNodesCount(); i++) {
+            LatLon center = w.getNode(i).getCoor().getCenter(w.getNode(i-1).getCoor());
             if (center != null && !isInPolygon(new Node(center), polygon)) {
                 return false;
@@ -85,7 +83,5 @@
     public void endTest() {
         for (final OsmPrimitive p : primitivesToCheck) {
-            Collection<Way> outer = index.search(p.getBBox());
-            outer = new FilteredCollection<Way>(outer, new Predicate<Way>() {
-
+            Collection<Way> outers = new FilteredCollection<Way>(index.search(p.getBBox()), new Predicate<Way>() {
                 @Override
                 public boolean evaluate(Way object) {
@@ -95,5 +91,5 @@
                         return isInPolygon((Node) p, object.getNodes()) || object.getNodes().contains(p);
                     } else if (p instanceof Way) {
-                        return isInPolygon((Way) p, object.getNodes());
+                        return isInPolygon((Way) p, object.getNodes()) && !isInInnerWay((Way)p, object);
                     } else {
                         return false;
@@ -101,9 +97,29 @@
                 }
             });
-            if (!outer.isEmpty()) {
+            if (!outers.isEmpty()) {
                 errors.add(new TestError(this, Severity.WARNING,
                         tr("Building inside building"), BUILDING_INSIDE_BUILDING, p));
             }
         }
+    }
+    
+    private boolean isInInnerWay(Way w, Way outer) {
+        for (OsmPrimitive r : outer.getReferrers()) {
+            if (r instanceof Relation && ((Relation)r).isMultipolygon()) {
+                for (RelationMember m : ((Relation)r).getMembers()) {
+                    if (m.hasRole() && m.getRole().equals("inner") && m.getType().equals(OsmPrimitiveType.WAY)) {
+                        // Only check inner ways actually inside the current outer
+                        Way inner = m.getWay();
+                        if (isInPolygon(inner, outer.getNodes())) {
+                            // If the tested way is inside this inner, outer is a false positive
+                            if (isInPolygon(w, inner.getNodes())) {
+                                return true;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return false;
     }
 
