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