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