Ticket #20019: 20019.3.patch

File 20019.3.patch, 4.8 KB (added by GerdP, 4 months ago)
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

     
    4444import org.openstreetmap.josm.data.validation.tests.ConditionalKeys;
    4545import org.openstreetmap.josm.data.validation.tests.ConnectivityRelations;
    4646import org.openstreetmap.josm.data.validation.tests.CrossingWays;
     47import org.openstreetmap.josm.data.validation.tests.DirectionNodes;
    4748import org.openstreetmap.josm.data.validation.tests.DuplicateNode;
    4849import org.openstreetmap.josm.data.validation.tests.DuplicateRelation;
    4950import org.openstreetmap.josm.data.validation.tests.DuplicateWay;
     
    151152        RightAngleBuildingTest.class, // 3700 .. 3799
    152153        SharpAngles.class, // 3800 .. 3899
    153154        ConnectivityRelations.class, // 3900 .. 3999
     155        DirectionNodes.class, // 4000-4099
    154156    };
    155157
    156158    /**
  • src/org/openstreetmap/josm/data/validation/tests/DirectionNodes.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.data.validation.tests;
     3
     4import static org.openstreetmap.josm.tools.I18n.marktr;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6
     7import java.util.ArrayList;
     8import java.util.List;
     9import java.util.Map.Entry;
     10
     11import org.openstreetmap.josm.data.osm.Node;
     12import org.openstreetmap.josm.data.osm.OsmPrimitive;
     13import org.openstreetmap.josm.data.osm.Way;
     14import org.openstreetmap.josm.data.validation.Severity;
     15import org.openstreetmap.josm.data.validation.Test;
     16import org.openstreetmap.josm.data.validation.TestError;
     17
     18/**
     19 * Find nodes with direction tag and invalid number of parent ways or position in way. See #20019.
     20 * @author Gerd Petermann
     21 * @since xxx
     22 */
     23public class DirectionNodes extends Test {
     24    private static final int MULTIPLE_WAYS_CODE = 4000;
     25    private static final int END_NODE_CODE = 4001;
     26    private static final int NO_WAY_CODE = 4002;
     27
     28    private static final String DIR_VERIF_PROBLEM_MSG = tr("Invalid usage of direction on node");
     29
     30    /**
     31     * Construct a new {@code DirectionNodes} object
     32     */
     33    public DirectionNodes() {
     34        super(tr("Direction nodes"), tr("Check for nodes which have a 'forward' or 'backward' direction"));
     35    }
     36
     37    @Override
     38    public void visit(Node n) {
     39        if (!n.isUsable() || !n.isTagged())
     40            return;
     41        for (Entry<String, String> tag : n.getKeys().entrySet()) {
     42            if (("forward".equals(tag.getValue()) || "backward".equals(tag.getValue())
     43                    && ("direction".equals(tag.getKey()) || tag.getKey().endsWith(":direction")))) {
     44                checkParents(n, tag.toString());
     45            }
     46        }
     47    }
     48
     49    private static boolean isSuitableParentWay(Way w) {
     50        return w.hasKey("highway", "railway", "waterway") || w.hasTag("man_made", "pipeline");
     51    }
     52
     53    private void checkParents(Node n, String tag) {
     54        final List<Way> ways = new ArrayList<>();
     55        int count = 0;
     56        for (Way w : n.getParentWays()) {
     57            if (isSuitableParentWay(w)) {
     58                ways.add(w);
     59            }
     60            count++;
     61        }
     62        boolean needsParentWays = n.isNew() || (!n.isOutsideDownloadArea() && n.getDataSet().getDataSourceArea() != null);
     63        TestError.Builder builder = null;
     64        if (ways.isEmpty() && needsParentWays) {
     65            if (count == 0) {
     66                builder = TestError.builder(this, Severity.WARNING, NO_WAY_CODE).message(DIR_VERIF_PROBLEM_MSG,
     67                        marktr("Unconnected node with {0}"), tag);
     68            }
     69
     70        } else if (ways.size() == 1) {
     71            Way w = ways.get(0);
     72            if (w.firstNode() == n || w.lastNode() == n) {
     73                builder = TestError.builder(this, Severity.WARNING, END_NODE_CODE).message(DIR_VERIF_PROBLEM_MSG,
     74                        marktr("Node with {0} on end of way"), tag);
     75            }
     76        } else if (ways.size() > 1) {
     77            builder = TestError.builder(this, Severity.WARNING, MULTIPLE_WAYS_CODE).message(DIR_VERIF_PROBLEM_MSG,
     78                    marktr("Node with {0} on a connection of multiple ways"), tag);
     79        }
     80        if (builder != null) {
     81            List<OsmPrimitive> primitives = new ArrayList<>();
     82            primitives.add(n);
     83            primitives.addAll(ways);
     84            errors.add(builder.primitives(primitives).highlight(n).build());
     85        }
     86    }
     87}