Ticket #17188: 17188_v5.patch

File 17188_v5.patch, 8.7 KB (added by reichg, 5 years ago)

addressing checkstyle and translations

  • src/org/openstreetmap/josm/data/validation/tests/Highways.java

     
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.validation.tests;
    33
    4 import static org.openstreetmap.josm.data.validation.tests.CrossingWays.HIGHWAY;
    5 import static org.openstreetmap.josm.tools.I18n.tr;
    6 
     4import javax.swing.JButton;
     5import javax.swing.JFormattedTextField;
     6import javax.swing.JLabel;
     7import javax.swing.JPanel;
     8import javax.swing.event.DocumentEvent;
     9import javax.swing.event.DocumentListener;
     10import java.awt.Color;
     11import java.awt.event.ActionListener;
     12import java.text.DecimalFormat;
    713import java.util.ArrayList;
    814import java.util.Arrays;
    915import java.util.HashMap;
     
    1521import java.util.stream.Collectors;
    1622
    1723import org.openstreetmap.josm.command.ChangePropertyCommand;
     24import org.openstreetmap.josm.data.osm.BBox;
     25import org.openstreetmap.josm.data.osm.DataSet;
    1826import org.openstreetmap.josm.data.osm.Node;
    1927import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2028import org.openstreetmap.josm.data.osm.OsmUtils;
     
    2230import org.openstreetmap.josm.data.validation.Severity;
    2331import org.openstreetmap.josm.data.validation.Test;
    2432import org.openstreetmap.josm.data.validation.TestError;
     33import org.openstreetmap.josm.spi.preferences.Config;
     34import org.openstreetmap.josm.spi.preferences.IPreferences;
     35import org.openstreetmap.josm.tools.GBC;
    2536import org.openstreetmap.josm.tools.Logging;
    2637import org.openstreetmap.josm.tools.Utils;
    2738
     39import static org.openstreetmap.josm.data.validation.tests.CrossingWays.HIGHWAY;
     40import static org.openstreetmap.josm.tools.I18n.tr;
     41
    2842/**
    2943 * Test that performs semantic checks on highways.
    3044 * @since 5902
     
    3852    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_MAXSPEED = 2705;
    3953    protected static final int SOURCE_MAXSPEED_CONTEXT_MISMATCH_VS_HIGHWAY = 2706;
    4054    protected static final int SOURCE_WRONG_LINK = 2707;
     55    protected static final int SOURCE_BUS_STOP_NEEDED = 2708;
    4156
    4257    protected static final String SOURCE_MAXSPEED = "source:maxspeed";
     58    protected static final String BUS = "bus";
     59    protected static final String PUBLIC_TRANSPORT = "public_transport";
    4360
     61    private final JFormattedTextField formattedTextField;
     62    private final JLabel warningLabel;
     63    private final JButton defaultButton;
     64
     65    private final JLabel labelForBboxExpansion;
     66    private static final String BBOX_EXPANSION_PREF_KEY = "bboxExpansionConstant";
     67    private static final double EXPANSE_DISTANCE_DEFAULT = 0.00015;
     68    private final IPreferences preferences = Config.getPref();
     69
     70    private final ActionListener actionListener;
     71    private final DocumentListener documentListener;
     72
    4473    /**
    4574     * Classified highways in order of importance
    4675     */
     
    73102     * Constructs a new {@code Highways} test.
    74103     */
    75104    public Highways() {
     105
    76106        super(tr("Highways"), tr("Performs semantic checks on highways."));
     107
     108        labelForBboxExpansion = new JLabel(tr("Enter bbox expansion constant for searching nearby Nodes " +
     109                "(LatLon degrees, Default value is approximately {0} meters) ", 15));
     110        formattedTextField = new JFormattedTextField(new DecimalFormat("#.########"));
     111        defaultButton = new JButton("Set Default");
     112        warningLabel = new JLabel("Entry must be a valid number.");
     113        warningLabel.setVisible(false);
     114        warningLabel.setForeground(Color.RED);
     115        documentListener = new DocumentListener() {
     116            @Override
     117            public void insertUpdate(DocumentEvent e) {
     118                warn();
     119            }
     120
     121            @Override
     122            public void removeUpdate(DocumentEvent e) {
     123                warn();
     124            }
     125
     126            @Override
     127            public void changedUpdate(DocumentEvent e) {
     128                //unneeded for this listener's purpose.
     129            }
     130        };
     131        actionListener = e -> {
     132            formattedTextField.setValue(EXPANSE_DISTANCE_DEFAULT);
     133        };
    77134    }
    78135
    79136    @Override
     
    90147                // as maxspeed is not set on highways here but on signs, speed cameras, etc.
    91148                testSourceMaxspeed(n, false);
    92149            }
     150            if ((IN_DOWNLOADED_AREA.test(n) || n.isNew()) && n.hasTag(BUS, "yes") && n.hasTag(PUBLIC_TRANSPORT, "stop_position")) {
     151                // Test for 17188: complain about bus stop position without nearby highway=bus_stop
     152                testMissingBusStopNode(n);
     153            }
    93154        }
    94155    }
    95156
     
    243304        }
    244305    }
    245306
     307    /**
     308     * Tests for bus stop ("public_transport"="stop_position"/"bus"="yes") Nodes along a way that are
     309     * missing a related nearby Node with "highway=bus_stop"
     310     *
     311     * @param n Node being visited
     312     */
     313    public void testMissingBusStopNode(Node n) {
     314        int countOfNodesWithProperTags = 0;
     315        double expanseDistance = EXPANSE_DISTANCE_DEFAULT;
     316
     317        //Approximately 15 meters depending on Lat/Lon
     318        String expanseDistanceFromPrefs = preferences.get(BBOX_EXPANSION_PREF_KEY);
     319        if (expanseDistanceFromPrefs != null && !expanseDistanceFromPrefs.isEmpty()) {
     320            expanseDistance = Double.parseDouble(expanseDistanceFromPrefs);
     321        }
     322        List<Node> nearbyNodesWithinTwentyFiveMeters = getNearbyNodesWithinShortDistance(n, expanseDistance);
     323        for (Node nearbyNodeWithinTwentyFiveMeters : nearbyNodesWithinTwentyFiveMeters) {
     324            if (nearbyNodeWithinTwentyFiveMeters.hasTag(HIGHWAY, "bus_stop") && nearbyNodeWithinTwentyFiveMeters.hasTag(BUS, "yes")) {
     325                countOfNodesWithProperTags += 1;
     326            }
     327        }
     328        if (countOfNodesWithProperTags == 0) {
     329            errors.add(TestError.builder(this, Severity.WARNING, SOURCE_BUS_STOP_NEEDED)
     330                    .message(tr("Node needs a nearby related Node with tags: {0} and {1}.",
     331                            "highway=bus_stop", "bus=yes"))
     332                    .primitives(n)
     333                    .build());
     334        }
     335    }
     336
     337    /**
     338     * Gathers list of Nodes within specified approximate distance (takes double but unit is LatLon degrees) of Node n.
     339     *
     340     * @param n               Node being visited
     341     * @param expanseDistance Distance to expand Node bounds. Units are in LatLon degrees.
     342     * @return List of Nodes
     343     */
     344    public List<Node> getNearbyNodesWithinShortDistance(Node n, double expanseDistance) {
     345        DataSet nodeDataSet = n.getDataSet();
     346
     347        BBox nodeBBox = n.getBBox();
     348        nodeBBox.addLatLon(nodeBBox.getCenter(), expanseDistance);
     349
     350        return nodeDataSet.searchNodes(nodeBBox);
     351    }
     352
    246353    private void handleCarWay(Node n, Way w) {
    247354        carsWays++;
    248355        if (!w.isFirstLastNode(n) || carsWays > 1) {
     
    295402            }
    296403        }
    297404    }
     405
     406    @Override
     407    public void addGui(JPanel testPanel) {
     408        super.addGui(testPanel);
     409        String bboxExpansionPref = preferences.get(BBOX_EXPANSION_PREF_KEY);
     410        if (bboxExpansionPref != null && !bboxExpansionPref.isEmpty()) {
     411            try {
     412                Double.parseDouble(bboxExpansionPref);
     413                formattedTextField.setValue(Double.parseDouble(bboxExpansionPref));
     414            } catch (Exception exception) {
     415                formattedTextField.setValue(EXPANSE_DISTANCE_DEFAULT);
     416            }
     417        } else {
     418            formattedTextField.setValue(EXPANSE_DISTANCE_DEFAULT);
     419        }
     420        formattedTextField.setColumns(5);
     421        formattedTextField.getDocument().addDocumentListener(documentListener);
     422        defaultButton.addActionListener(actionListener);
     423        testPanel.add(labelForBboxExpansion, GBC.eol().insets(20, 0, 0, 0));
     424        testPanel.add(formattedTextField, GBC.eol().insets(20, 0, 0, 0));
     425        testPanel.add(warningLabel, GBC.eol().insets(20, 0, 0, 0));
     426        testPanel.add(defaultButton, GBC.eol().insets(20, 0, 0, 0));
     427    }
     428
     429    public void warn() {
     430        String expansionDegrees = formattedTextField.getText();
     431        if (expansionDegrees.equals(".") || expansionDegrees.equals("")) {
     432            expansionDegrees = "0";
     433        }
     434        try {
     435            Double.parseDouble(expansionDegrees);
     436            warningLabel.setVisible(false);
     437        } catch (Exception exception) {
     438            warningLabel.setVisible(true);
     439        }
     440    }
     441
     442    @Override
     443    public boolean ok() {
     444        //Uses most recent VALID entry for bbox expanse on OK
     445        preferences.put(BBOX_EXPANSION_PREF_KEY, formattedTextField.getValue().toString());
     446        return false;
     447    }
    298448}