Ticket #13429: patch-validator-cleanup-and-use-listener.patch

File patch-validator-cleanup-and-use-listener.patch, 23.3 KB (added by michael2402, 8 years ago)
  • src/org/openstreetmap/josm/actions/ValidateAction.java

    diff --git a/src/org/openstreetmap/josm/actions/ValidateAction.java b/src/org/openstreetmap/josm/actions/ValidateAction.java
    index 12febf6..4f2851f 100644
    a b public class ValidateAction extends JosmAction {  
    168168                errors.addAll(test.getErrors());
    169169            }
    170170            tests = null;
    171             if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) {
     171            if (ValidatorPreference.PREF_USE_IGNORE.get()) {
    172172                getProgressMonitor().subTask(tr("Updating ignored errors ..."));
    173173                for (TestError error : errors) {
    174174                    if (canceled) return;
  • src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java

    diff --git a/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java b/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java
    index 2704956..6d32ccf 100644
    a b public class ValidateUploadHook implements UploadHook {  
    6060            test.startTest(null);
    6161            test.visit(selection);
    6262            test.endTest();
    63             if (ValidatorPreference.PREF_OTHER.get() &&
    64                 Main.pref.getBoolean(ValidatorPreference.PREF_OTHER_UPLOAD, false)) {
     63            if (ValidatorPreference.PREF_OTHER.get() && ValidatorPreference.PREF_OTHER_UPLOAD.get()) {
    6564                errors.addAll(test.getErrors());
    6665            } else {
    6766                for (TestError e : test.getErrors()) {
    public class ValidateUploadHook implements UploadHook {  
    8281        if (errors.isEmpty())
    8382            return true;
    8483
    85         if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) {
     84        if (ValidatorPreference.PREF_USE_IGNORE.get()) {
    8685            int nume = 0;
    8786            for (TestError error : errors) {
    8887                List<String> s = new ArrayList<>();
  • src/org/openstreetmap/josm/data/validation/OsmValidator.java

    diff --git a/src/org/openstreetmap/josm/data/validation/OsmValidator.java b/src/org/openstreetmap/josm/data/validation/OsmValidator.java
    index fc4da6b..a25960d 100644
    a b public final class OsmValidator {  
    182182
    183183    private static void loadIgnoredErrors() {
    184184        ignoredErrors.clear();
    185         if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) {
     185        if (ValidatorPreference.PREF_USE_IGNORE.get()) {
    186186            Path path = Paths.get(getValidatorDir()).resolve("ignorederrors");
    187187            if (Files.exists(path)) {
    188188                try {
    public final class OsmValidator {  
    216216    }
    217217
    218218    public static synchronized void initializeErrorLayer() {
    219         if (!Main.pref.getBoolean(ValidatorPreference.PREF_LAYER, true))
     219        if (!ValidatorPreference.PREF_LAYER.get())
    220220            return;
    221221        if (errorLayer == null) {
    222222            errorLayer = new ValidatorLayer();
  • src/org/openstreetmap/josm/data/validation/TestError.java

    diff --git a/src/org/openstreetmap/josm/data/validation/TestError.java b/src/org/openstreetmap/josm/data/validation/TestError.java
    index d9d86a7..9379629 100644
    a b public class TestError implements Comparable<TestError>, DataSetListener {  
    268268        return tester;
    269269    }
    270270
     271    /**
     272     * Set the tester that raised the error.
     273     * @param tester te tester
     274     */
    271275    public void setTester(Test tester) {
    272276        this.tester = tester;
    273277    }
  • src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java b/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java
    index a3e121a..7ae55df 100644
    a b public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis  
    150150        fixButton.setEnabled(false);
    151151        buttons.add(fixButton);
    152152
    153         if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) {
     153        if (ValidatorPreference.PREF_USE_IGNORE.get()) {
    154154            ignoreButton = new SideButton(new AbstractAction() {
    155155                {
    156156                    putValue(NAME, tr("Ignore"));
    public class ValidatorDialog extends ToggleDialog implements SelectionChangedLis  
    192192            tree.setVisible(v);
    193193        }
    194194        super.setVisible(v);
    195         Main.map.repaint();
    196195    }
    197196
    198197    /**
  • src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java

    diff --git a/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java b/src/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanel.java
    index fd212c8..a399bdf 100644
    a b import java.util.Collection;  
    1010import java.util.Collections;
    1111import java.util.EnumMap;
    1212import java.util.Enumeration;
    13 import java.util.HashMap;
    1413import java.util.HashSet;
    1514import java.util.List;
    1615import java.util.Map;
    1716import java.util.Map.Entry;
    1817import java.util.Set;
    1918import java.util.function.Predicate;
     19import java.util.stream.Collectors;
    2020
    2121import javax.swing.JTree;
    2222import javax.swing.ToolTipManager;
    import org.openstreetmap.josm.data.validation.util.MultipleNameVisitor;  
    3535import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference;
    3636import org.openstreetmap.josm.gui.util.GuiHelper;
    3737import org.openstreetmap.josm.tools.Destroyable;
    38 import org.openstreetmap.josm.tools.MultiMap;
     38import org.openstreetmap.josm.tools.ListenerList;
    3939
    4040/**
    4141 * A panel that displays the error tree. The selection manager
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    7272     */
    7373    private transient Set<? extends OsmPrimitive> filter;
    7474
    75     /** a counter to check if tree has been rebuild */
    76     private int updateCount;
     75    private final ListenerList<Runnable> invalidationListeners = ListenerList.create();
    7776
    7877    /**
    7978     * Constructor
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    134133            valTreeModel.setRoot(new DefaultMutableTreeNode());
    135134        }
    136135        super.setVisible(v);
     136        invalidationListeners.fireEvent(Runnable::run);
    137137    }
    138138
    139139    /**
    140140     * Builds the errors tree
    141141     */
    142142    public void buildTree() {
    143         updateCount++;
    144143        final DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode();
    145144
    146145        if (errors == null || errors.isEmpty()) {
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    171170            }
    172171        }
    173172
    174         Map<Severity, MultiMap<String, TestError>> errorTree = new EnumMap<>(Severity.class);
    175         Map<Severity, HashMap<String, MultiMap<String, TestError>>> errorTreeDeep = new EnumMap<>(Severity.class);
    176         for (Severity s : Severity.values()) {
    177             errorTree.put(s, new MultiMap<String, TestError>(20));
    178             errorTreeDeep.put(s, new HashMap<String, MultiMap<String, TestError>>());
     173        Predicate<TestError> filterToUse = e -> !e.isIgnored();
     174        if (!ValidatorPreference.PREF_OTHER.get()) {
     175            filterToUse = filterToUse.and(e -> e.getSeverity() != Severity.OTHER);
    179176        }
    180 
    181         final Boolean other = ValidatorPreference.PREF_OTHER.get();
    182         for (TestError e : errors) {
    183             if (e.isIgnored()) {
    184                 continue;
    185             }
    186             Severity s = e.getSeverity();
    187             if (!other && s == Severity.OTHER) {
    188                 continue;
    189             }
    190             String d = e.getDescription();
    191             String m = e.getMessage();
    192             if (filter != null) {
    193                 boolean found = false;
    194                 for (OsmPrimitive p : e.getPrimitives()) {
    195                     if (filter.contains(p)) {
    196                         found = true;
    197                         break;
    198                     }
    199                 }
    200                 if (!found) {
    201                     continue;
    202                 }
    203             }
    204             if (d != null) {
    205                 MultiMap<String, TestError> b = errorTreeDeep.get(s).get(m);
    206                 if (b == null) {
    207                     b = new MultiMap<>(20);
    208                     errorTreeDeep.get(s).put(m, b);
    209                 }
    210                 b.put(d, e);
    211             } else {
    212                 errorTree.get(s).put(m, e);
    213             }
     177        if (filter != null) {
     178            filterToUse = filterToUse.and(e -> e.getPrimitives().stream().anyMatch(filter::contains));
    214179        }
     180        Map<Severity, Map<String, Map<String, List<TestError>>>> errorTreeDeep
     181            = errors.stream().filter(filterToUse).collect(
     182                    Collectors.groupingBy(e -> e.getSeverity(), () -> new EnumMap<>(Severity.class),
     183                            Collectors.groupingBy(e -> e.getDescription() == null ? "" : e.getDescription(),
     184                                    Collectors.groupingBy(e -> e.getMessage()))));
    215185
    216186        List<TreePath> expandedPaths = new ArrayList<>();
    217         for (Severity s : Severity.values()) {
    218             MultiMap<String, TestError> severityErrors = errorTree.get(s);
    219             Map<String, MultiMap<String, TestError>> severityErrorsDeep = errorTreeDeep.get(s);
    220             if (severityErrors.isEmpty() && severityErrorsDeep.isEmpty()) {
    221                 continue;
    222             }
    223 
     187        errorTreeDeep.forEach((s, severityErrorsDeep) -> {
    224188            // Severity node
    225189            DefaultMutableTreeNode severityNode = new GroupTreeNode(s);
    226190            rootNode.add(severityNode);
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    229193                expandedPaths.add(new TreePath(new Object[] {rootNode, severityNode}));
    230194            }
    231195
    232             for (Entry<String, Set<TestError>> msgErrors : severityErrors.entrySet()) {
    233                 // Message node
    234                 Set<TestError> errs = msgErrors.getValue();
    235                 String msg = tr("{0} ({1})", msgErrors.getKey(), errs.size());
    236                 DefaultMutableTreeNode messageNode = new DefaultMutableTreeNode(msg);
    237                 severityNode.add(messageNode);
     196            Map<String, List<TestError>> severityErrors = severityErrorsDeep.get("");
     197            if (severityErrors != null) {
     198                for (Entry<String, List<TestError>> msgErrors : severityErrors.entrySet()) {
     199                    // Message node
     200                    List<TestError> errs = msgErrors.getValue();
     201                    String msg = tr("{0} ({1})", msgErrors.getKey(), errs.size());
     202                    DefaultMutableTreeNode messageNode = new DefaultMutableTreeNode(msg);
     203                    severityNode.add(messageNode);
    238204
    239                 if (oldSelectedRows.contains(msgErrors.getKey())) {
    240                     expandedPaths.add(new TreePath(new Object[] {rootNode, severityNode, messageNode}));
    241                 }
     205                    if (oldSelectedRows.contains(msgErrors.getKey())) {
     206                        expandedPaths.add(new TreePath(new Object[] {rootNode, severityNode, messageNode}));
     207                    }
    242208
    243                 for (TestError error : errs) {
    244                     // Error node
    245                     DefaultMutableTreeNode errorNode = new DefaultMutableTreeNode(error);
    246                     messageNode.add(errorNode);
     209                    errs.stream().map(DefaultMutableTreeNode::new).forEach(messageNode::add);
    247210                }
    248211            }
    249             for (Entry<String, MultiMap<String, TestError>> bag : severityErrorsDeep.entrySet()) {
     212
     213            severityErrorsDeep.forEach((description, errorlist) -> {
     214                if (description.isEmpty()) {
     215                    return;
     216                }
    250217                // Group node
    251                 MultiMap<String, TestError> errorlist = bag.getValue();
    252                 DefaultMutableTreeNode groupNode = null;
     218                DefaultMutableTreeNode groupNode;
    253219                if (errorlist.size() > 1) {
    254                     groupNode = new GroupTreeNode(bag.getKey());
     220                    groupNode = new GroupTreeNode(description);
    255221                    severityNode.add(groupNode);
    256                     if (oldSelectedRows.contains(bag.getKey())) {
     222                    if (oldSelectedRows.contains(description)) {
    257223                        expandedPaths.add(new TreePath(new Object[] {rootNode, severityNode, groupNode}));
    258224                    }
     225                } else {
     226                    groupNode = null;
    259227                }
    260228
    261                 for (Entry<String, Set<TestError>> msgErrors : errorlist.entrySet()) {
     229                errorlist.forEach((message, errs) -> {
    262230                    // Message node
    263                     Set<TestError> errs = msgErrors.getValue();
    264231                    String msg;
    265232                    if (groupNode != null) {
    266                         msg = tr("{0} ({1})", msgErrors.getKey(), errs.size());
     233                        msg = tr("{0} ({1})", message, errs.size());
    267234                    } else {
    268                         msg = tr("{0} - {1} ({2})", msgErrors.getKey(), bag.getKey(), errs.size());
     235                        msg = tr("{0} - {1} ({2})", message, description, errs.size());
    269236                    }
    270237                    DefaultMutableTreeNode messageNode = new DefaultMutableTreeNode(msg);
    271238                    if (groupNode != null) {
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    274241                        severityNode.add(messageNode);
    275242                    }
    276243
    277                     if (oldSelectedRows.contains(msgErrors.getKey())) {
     244                    if (oldSelectedRows.contains(message)) {
    278245                        if (groupNode != null) {
    279246                            expandedPaths.add(new TreePath(new Object[] {rootNode, severityNode, groupNode, messageNode}));
    280247                        } else {
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    282249                        }
    283250                    }
    284251
    285                     for (TestError error : errs) {
    286                         // Error node
    287                         DefaultMutableTreeNode errorNode = new DefaultMutableTreeNode(error);
    288                         messageNode.add(errorNode);
    289                     }
    290                 }
    291             }
    292         }
     252                    errs.stream().map(DefaultMutableTreeNode::new).forEach(messageNode::add);
     253                });
     254            });
     255        });
    293256
    294257        valTreeModel.setRoot(rootNode);
    295258        for (TreePath path : expandedPaths) {
    296259            this.expandPath(path);
    297260        }
     261
     262        invalidationListeners.fireEvent(Runnable::run);
     263    }
     264
     265    /**
     266     * Add a new invalidation listener
     267     * @param listener The listener
     268     */
     269    public void addInvalidationListener(Runnable listener) {
     270        invalidationListeners.addListener(listener);
     271    }
     272
     273    /**
     274     * Remove an invalidation listener
     275     * @param listener The listener
     276     */
     277    public void removeInvalidationListener(Runnable listener) {
     278        invalidationListeners.removeListener(listener);
    298279    }
    299280
    300281    /**
    public class ValidatorTreePanel extends JTree implements Destroyable {  
    425406        return (DefaultMutableTreeNode) valTreeModel.getRoot();
    426407    }
    427408
    428     /**
    429      * Returns a value to check if tree has been rebuild
    430      * @return the current counter
    431      */
    432     public int getUpdateCount() {
    433         return updateCount;
    434     }
    435 
    436409    private void clearErrors() {
    437410        if (errors != null) {
    438411            DataSet ds = Main.getLayerManager().getEditDataSet();
  • src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java b/src/org/openstreetmap/josm/gui/layer/ValidatorLayer.java
    index 4044d99..cc52120 100644
    a b import org.openstreetmap.josm.tools.MultiMap;  
    4040 * @since 10386 (new LayerChangeListener interface)
    4141 */
    4242public class ValidatorLayer extends Layer implements LayerChangeListener {
    43 
    44     private int updateCount = -1;
     43    private final Runnable invalidator = this::invalidate;
    4544
    4645    /**
    4746     * Constructs a new Validator layer
    public class ValidatorLayer extends Layer implements LayerChangeListener {  
    4948    public ValidatorLayer() {
    5049        super(tr("Validation errors"));
    5150        Main.getLayerManager().addLayerChangeListener(this);
     51        Main.map.validatorDialog.tree.addInvalidationListener(invalidator);
    5252    }
    5353
    5454    /**
    public class ValidatorLayer extends Layer implements LayerChangeListener {  
    6767    @SuppressWarnings("unchecked")
    6868    @Override
    6969    public void paint(final Graphics2D g, final MapView mv, Bounds bounds) {
    70         updateCount = Main.map.validatorDialog.tree.getUpdateCount();
    7170        DefaultMutableTreeNode root = Main.map.validatorDialog.tree.getRoot();
    7271        if (root == null || root.getChildCount() == 0)
    7372            return;
    public class ValidatorLayer extends Layer implements LayerChangeListener {  
    123122    }
    124123
    125124    @Override
    126     public boolean isChanged() {
    127         return updateCount != Main.map.validatorDialog.tree.getUpdateCount();
    128     }
    129 
    130     @Override
    131125    public void visitBoundingBox(BoundingXYVisitor v) {
    132126        // Do nothing
    133127    }
    public class ValidatorLayer extends Layer implements LayerChangeListener {  
    167161        if (e.getRemovedLayer() instanceof OsmDataLayer && e.getSource().getLayersOfType(OsmDataLayer.class).size() <= 1) {
    168162            e.scheduleRemoval(Collections.singleton(this));
    169163        } else if (e.getRemovedLayer() == this) {
    170             Main.getLayerManager().removeLayerChangeListener(this);
    171164            OsmValidator.errorLayer = null;
    172165        }
    173166    }
    public class ValidatorLayer extends Layer implements LayerChangeListener {  
    176169    public LayerPositionStrategy getDefaultLayerPosition() {
    177170        return LayerPositionStrategy.IN_FRONT;
    178171    }
     172
     173    @Override
     174    public void destroy() {
     175        Main.map.validatorDialog.tree.removeInvalidationListener(invalidator);
     176        Main.getLayerManager().removeLayerChangeListener(this);
     177        super.destroy();
     178    }
    179179}
  • src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java

    diff --git a/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java b/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorPreference.java
    index f647d56..24ec975 100644
    a b public final class ValidatorPreference extends DefaultTabPreferenceSetting {  
    3939    public static final String PREFIX = "validator";
    4040
    4141    /** The preferences key for error layer */
    42     public static final String PREF_LAYER = PREFIX + ".layer";
     42    public static final BooleanProperty PREF_LAYER = new BooleanProperty(PREFIX + ".layer", true);
    4343
    4444    /** The preferences key for enabled tests */
    4545    public static final String PREF_SKIP_TESTS = PREFIX + ".skip";
    4646
    4747    /** The preferences key for enabled tests */
    48     public static final String PREF_USE_IGNORE = PREFIX + ".ignore";
     48    public static final BooleanProperty PREF_USE_IGNORE = new BooleanProperty(PREFIX + ".ignore", true);
    4949
    5050    /** The preferences key for enabled tests before upload*/
    5151    public static final String PREF_SKIP_TESTS_BEFORE_UPLOAD = PREFIX + ".skipBeforeUpload";
    5252
    5353    /** The preferences key for ignored severity other on upload */
    54     public static final String PREF_OTHER_UPLOAD = PREFIX + ".otherUpload";
     54    public static final BooleanProperty PREF_OTHER_UPLOAD = new BooleanProperty(PREFIX + ".otherUpload", false);
    5555
    5656    /** The preferences for ignored severity other */
    5757    public static final BooleanProperty PREF_OTHER = new BooleanProperty(PREFIX + ".other", false);
  • src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTestsPreference.java

    diff --git a/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTestsPreference.java b/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTestsPreference.java
    index 67b1a7e..3a4128a 100644
    a b public class ValidatorTestsPreference implements SubPreferenceSetting {  
    5757        JPanel testPanel = new VerticallyScrollablePanel(new GridBagLayout());
    5858        testPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
    5959
    60         prefUseIgnore = new JCheckBox(tr("Use ignore list."), Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true));
     60        prefUseIgnore = new JCheckBox(tr("Use ignore list."), ValidatorPreference.PREF_USE_IGNORE.get());
    6161        prefUseIgnore.setToolTipText(tr("Use the ignore list to suppress warnings."));
    6262        testPanel.add(prefUseIgnore, GBC.eol());
    6363
    64         prefUseLayer = new JCheckBox(tr("Use error layer."), Main.pref.getBoolean(ValidatorPreference.PREF_LAYER, true));
     64        prefUseLayer = new JCheckBox(tr("Use error layer."), ValidatorPreference.PREF_LAYER.get());
    6565        prefUseLayer.setToolTipText(tr("Use the error layer to display problematic elements."));
    6666        testPanel.add(prefUseLayer, GBC.eol());
    6767
    public class ValidatorTestsPreference implements SubPreferenceSetting {  
    7070        testPanel.add(prefOther, GBC.eol());
    7171
    7272        prefOtherUpload = new JCheckBox(tr("Show informational level on upload."),
    73                 Main.pref.getBoolean(ValidatorPreference.PREF_OTHER_UPLOAD, false));
     73                ValidatorPreference.PREF_OTHER_UPLOAD.get());
    7474        prefOtherUpload.setToolTipText(tr("Show the informational tests in the upload check windows."));
    7575        testPanel.add(prefOtherUpload, GBC.eol());
    7676
    public class ValidatorTestsPreference implements SubPreferenceSetting {  
    116116
    117117        Main.pref.putCollection(ValidatorPreference.PREF_SKIP_TESTS, tests);
    118118        Main.pref.putCollection(ValidatorPreference.PREF_SKIP_TESTS_BEFORE_UPLOAD, testsBeforeUpload);
    119         Main.pref.put(ValidatorPreference.PREF_USE_IGNORE, prefUseIgnore.isSelected());
     119        ValidatorPreference.PREF_USE_IGNORE.put(prefUseIgnore.isSelected());
    120120        ValidatorPreference.PREF_OTHER.put(prefOther.isSelected());
    121         Main.pref.put(ValidatorPreference.PREF_OTHER_UPLOAD, prefOtherUpload.isSelected());
    122         Main.pref.put(ValidatorPreference.PREF_LAYER, prefUseLayer.isSelected());
     121        ValidatorPreference.PREF_OTHER_UPLOAD.put(prefOtherUpload.isSelected());
     122        ValidatorPreference.PREF_LAYER.put(prefUseLayer.isSelected());
    123123        return false;
    124124    }
    125125
  • test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java

    diff --git a/test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java b/test/unit/org/openstreetmap/josm/gui/dialogs/validator/ValidatorTreePanelTest.java
    index 58fc137..abf7c21 100644
    a b public class ValidatorTreePanelTest {  
    4343                new TestError(null, Severity.ERROR, "err", 0, new Node(1)),
    4444                new TestError(null, Severity.WARNING, "warn", 0, new Node(2)))));
    4545        assertNotNull(vtp);
    46         assertEquals(1, vtp.getUpdateCount());
    4746        assertEquals(2, vtp.getErrors().size());
    4847        vtp.setVisible(true);
    4948        vtp.setVisible(false);