001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions.upload; 003 004import static org.openstreetmap.josm.tools.I18n.tr; 005 006import java.awt.Dimension; 007import java.awt.GridBagLayout; 008import java.util.ArrayList; 009import java.util.Collection; 010import java.util.List; 011 012import javax.swing.JPanel; 013import javax.swing.JScrollPane; 014 015import org.openstreetmap.josm.Main; 016import org.openstreetmap.josm.actions.JosmAction; 017import org.openstreetmap.josm.data.APIDataSet; 018import org.openstreetmap.josm.data.osm.OsmPrimitive; 019import org.openstreetmap.josm.data.validation.OsmValidator; 020import org.openstreetmap.josm.data.validation.Severity; 021import org.openstreetmap.josm.data.validation.Test; 022import org.openstreetmap.josm.data.validation.TestError; 023import org.openstreetmap.josm.data.validation.util.AggregatePrimitivesVisitor; 024import org.openstreetmap.josm.gui.ExtendedDialog; 025import org.openstreetmap.josm.gui.dialogs.validator.ValidatorTreePanel; 026import org.openstreetmap.josm.gui.layer.OsmDataLayer; 027import org.openstreetmap.josm.gui.preferences.validator.ValidatorPreference; 028import org.openstreetmap.josm.gui.widgets.HtmlPanel; 029import org.openstreetmap.josm.tools.GBC; 030 031/** 032 * The action that does the validate thing. 033 * <p> 034 * This action iterates through all active tests and give them the data, so that 035 * each one can test it. 036 * 037 * @author frsantos 038 * @since 3669 039 */ 040public class ValidateUploadHook implements UploadHook { 041 042 /** 043 * Validate the modified data before uploading 044 */ 045 @Override 046 public boolean checkUpload(APIDataSet apiDataSet) { 047 048 OsmValidator.initializeTests(); 049 Collection<Test> tests = OsmValidator.getEnabledTests(true); 050 if (tests.isEmpty()) 051 return true; 052 053 AggregatePrimitivesVisitor v = new AggregatePrimitivesVisitor(); 054 v.visit(apiDataSet.getPrimitivesToAdd()); 055 Collection<OsmPrimitive> selection = v.visit(apiDataSet.getPrimitivesToUpdate()); 056 057 List<TestError> errors = new ArrayList<>(30); 058 for (Test test : tests) { 059 test.setBeforeUpload(true); 060 test.setPartialSelection(true); 061 test.startTest(null); 062 test.visit(selection); 063 test.endTest(); 064 if (ValidatorPreference.PREF_OTHER.get() && 065 Main.pref.getBoolean(ValidatorPreference.PREF_OTHER_UPLOAD, false)) { 066 errors.addAll(test.getErrors()); 067 } else { 068 for (TestError e : test.getErrors()) { 069 if (e.getSeverity() != Severity.OTHER) { 070 errors.add(e); 071 } 072 } 073 } 074 } 075 OsmDataLayer editLayer = JosmAction.getEditLayer(); 076 if (editLayer != null) { 077 editLayer.validationErrors.clear(); 078 editLayer.validationErrors.addAll(errors); 079 } 080 if (Main.map != null) { 081 Main.map.validatorDialog.tree.setErrors(errors); 082 } 083 if (errors.isEmpty()) 084 return true; 085 086 if (Main.pref.getBoolean(ValidatorPreference.PREF_USE_IGNORE, true)) { 087 int nume = 0; 088 for (TestError error : errors) { 089 List<String> s = new ArrayList<>(); 090 s.add(error.getIgnoreState()); 091 s.add(error.getIgnoreGroup()); 092 s.add(error.getIgnoreSubGroup()); 093 for (String state : s) { 094 if (state != null && OsmValidator.hasIgnoredError(state)) { 095 error.setIgnored(true); 096 } 097 } 098 if (!error.isIgnored()) { 099 ++nume; 100 } 101 } 102 if (nume == 0) 103 return true; 104 } 105 return displayErrorScreen(errors); 106 } 107 108 /** 109 * Displays a screen where the actions that would be taken are displayed and 110 * give the user the possibility to cancel the upload. 111 * @param errors The errors displayed in the screen 112 * @return <code>true</code>, if the upload should continue. <code>false</code> 113 * if the user requested cancel. 114 */ 115 private static boolean displayErrorScreen(List<TestError> errors) { 116 JPanel p = new JPanel(new GridBagLayout()); 117 ValidatorTreePanel errorPanel = new ValidatorTreePanel(errors); 118 errorPanel.expandAll(); 119 HtmlPanel pnlMessage = new HtmlPanel(); 120 pnlMessage.setText("<html><body>" 121 + tr("The following are results of automatic validation. Try fixing" 122 + " these, but be careful (don''t destroy valid data)." 123 + " When in doubt ignore them.<br>When you" 124 + " cancel this dialog, you can find the entries in the validator" 125 + " side panel to inspect them.") 126 + "<table align=\"center\">" 127 + "<tr><td align=\"left\"><b>"+tr("Errors") 128 + " </b></td><td align=\"left\">" 129 + tr("Usually this should be fixed.")+"</td></tr>" 130 + "<tr><td align=\"left\"><b>"+tr("Warnings") 131 + " </b></td><td align=\"left\">" 132 + tr("Fix these when possible.")+"</td></tr>" 133 + "<tr><td align=\"left\"><b>"+tr("Other") 134 + " </b></td><td align=\"left\">" 135 + tr("Informational warnings, expect many false entries.")+"</td></tr>" 136 + "</table>" 137 ); 138 pnlMessage.setPreferredSize(new Dimension(500, 150)); 139 p.add(pnlMessage, GBC.eol().fill(GBC.HORIZONTAL)); 140 p.add(new JScrollPane(errorPanel), GBC.eol().fill(GBC.BOTH)); 141 142 ExtendedDialog ed = new ExtendedDialog(Main.parent, 143 tr("Suspicious data found. Upload anyway?"), 144 new String[] {tr("Continue upload"), tr("Cancel")}); 145 ed.setButtonIcons(new String[] {"ok.png", "cancel.png"}); 146 ed.setContent(p); 147 ed.showDialog(); 148 149 if (ed.getValue() != 1) { 150 OsmValidator.initializeTests(); 151 OsmValidator.initializeErrorLayer(); 152 Main.map.validatorDialog.unfurlDialog(); 153 Main.main.getCurrentDataSet().fireSelectionChanged(); 154 return false; 155 } 156 return true; 157 } 158}