001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.ActionEvent;
007import java.awt.event.KeyEvent;
008import java.util.Collection;
009import java.util.Optional;
010
011import org.openstreetmap.josm.data.osm.OsmPrimitive;
012import org.openstreetmap.josm.data.validation.OsmValidator;
013import org.openstreetmap.josm.data.validation.Test;
014import org.openstreetmap.josm.data.validation.ValidationTask;
015import org.openstreetmap.josm.data.validation.util.AggregatePrimitivesVisitor;
016import org.openstreetmap.josm.gui.MainApplication;
017import org.openstreetmap.josm.gui.MapFrame;
018import org.openstreetmap.josm.tools.Shortcut;
019
020/**
021 * The action that does the validate thing.
022 * <p>
023 * This action iterates through all active tests and give them the data, so that
024 * each one can test it.
025 *
026 * @author frsantos
027 */
028public class ValidateAction extends JosmAction {
029
030    /** Last selection used to validate */
031    private transient Collection<OsmPrimitive> lastSelection;
032
033    /**
034     * Constructor
035     */
036    public ValidateAction() {
037        super(tr("Validation"), "dialogs/validator", tr("Performs the data validation"),
038                Shortcut.registerShortcut("tools:validate", tr("Validation"),
039                        KeyEvent.VK_V, Shortcut.SHIFT), true);
040    }
041
042    @Override
043    public void actionPerformed(ActionEvent ev) {
044        doValidate(true);
045    }
046
047    /**
048     * Does the validation.
049     * <p>
050     * If getSelectedItems is true, the selected items (or all items, if no one
051     * is selected) are validated. If it is false, last selected items are revalidated
052     *
053     * @param getSelectedItems If selected or last selected items must be validated
054     */
055    public void doValidate(boolean getSelectedItems) {
056        MapFrame map = MainApplication.getMap();
057        if (map == null || !map.isVisible())
058            return;
059
060        OsmValidator.initializeTests();
061
062        Collection<Test> tests = OsmValidator.getEnabledTests(false);
063        if (tests.isEmpty())
064            return;
065
066        Collection<OsmPrimitive> selection;
067        if (getSelectedItems) {
068            selection = getLayerManager().getActiveDataSet().getAllSelected();
069            if (selection.isEmpty()) {
070                selection = getLayerManager().getActiveDataSet().allNonDeletedPrimitives();
071                lastSelection = null;
072            } else {
073                AggregatePrimitivesVisitor v = new AggregatePrimitivesVisitor();
074                selection = v.visit(selection);
075                lastSelection = selection;
076            }
077        } else {
078            selection = Optional.ofNullable(lastSelection).orElseGet(
079                    () -> getLayerManager().getActiveDataSet().allNonDeletedPrimitives());
080        }
081
082        MainApplication.worker.submit(new ValidationTask(tests, selection, lastSelection));
083    }
084
085    @Override
086    public void updateEnabledState() {
087        setEnabled(getLayerManager().getActiveDataSet() != null);
088    }
089
090    @Override
091    public void destroy() {
092        // Hack - this action should stay forever because it could be added to toolbar
093        // Do not call super.destroy() here
094        lastSelection = null;
095    }
096
097}