source: josm/trunk/src/org/openstreetmap/josm/actions/UploadAction.java@ 10318

Last change on this file since 10318 was 9972, checked in by Don-vip, 8 years ago

sonar - remove unnecessary fully qualified names

  • Property svn:eol-style set to native
File size: 9.7 KB
RevLine 
[6380]1// License: GPL. For details, see LICENSE file.
[230]2package org.openstreetmap.josm.actions;
3
[2390]4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
[230]5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.util.LinkedList;
[6316]10import java.util.List;
[230]11
12import javax.swing.JOptionPane;
13
14import org.openstreetmap.josm.Main;
[2168]15import org.openstreetmap.josm.actions.upload.ApiPreconditionCheckerHook;
[5497]16import org.openstreetmap.josm.actions.upload.DiscardTagsHook;
[5621]17import org.openstreetmap.josm.actions.upload.FixDataHook;
[2168]18import org.openstreetmap.josm.actions.upload.RelationUploadOrderHook;
19import org.openstreetmap.josm.actions.upload.UploadHook;
[3669]20import org.openstreetmap.josm.actions.upload.ValidateUploadHook;
[2025]21import org.openstreetmap.josm.data.APIDataSet;
[1750]22import org.openstreetmap.josm.data.conflict.ConflictCollection;
[2979]23import org.openstreetmap.josm.gui.HelpAwareOptionPane;
[2081]24import org.openstreetmap.josm.gui.io.UploadDialog;
[2598]25import org.openstreetmap.josm.gui.io.UploadPrimitivesTask;
[7402]26import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
[2025]27import org.openstreetmap.josm.gui.layer.OsmDataLayer;
[5233]28import org.openstreetmap.josm.gui.util.GuiHelper;
[5025]29import org.openstreetmap.josm.tools.ImageProvider;
[1575]30import org.openstreetmap.josm.tools.Shortcut;
[230]31
32/**
[655]33 * Action that opens a connection to the osm server and uploads all changes.
[230]34 *
35 * An dialog is displayed asking the user to specify a rectangle to grab.
36 * The url and account settings from the preferences are used.
[1677]37 *
[1670]38 * If the upload fails this action offers various options to resolve conflicts.
[230]39 *
40 * @author imi
41 */
[9059]42public class UploadAction extends JosmAction {
[1169]43 /**
44 * The list of upload hooks. These hooks will be called one after the other
45 * when the user wants to upload data. Plugins can insert their own hooks here
46 * if they want to be able to veto an upload.
47 *
48 * Be default, the standard upload dialog is the only element in the list.
49 * Plugins should normally insert their code before that, so that the upload
50 * dialog is the last thing shown before upload really starts; on occasion
51 * however, a plugin might also want to insert something after that.
52 */
[7005]53 private static final List<UploadHook> uploadHooks = new LinkedList<>();
54 private static final List<UploadHook> lateUploadHooks = new LinkedList<>();
[8510]55
[2081]56 static {
[5621]57 /**
58 * Calls validator before upload.
59 */
[3669]60 uploadHooks.add(new ValidateUploadHook());
[5621]61
[1169]62 /**
[5621]63 * Fixes database errors
64 */
65 uploadHooks.add(new FixDataHook());
66
67 /**
[1691]68 * Checks server capabilities before upload.
69 */
[2168]70 uploadHooks.add(new ApiPreconditionCheckerHook());
[1691]71
72 /**
[2168]73 * Adjusts the upload order of new relations
74 */
75 uploadHooks.add(new RelationUploadOrderHook());
[5497]76
77 /**
78 * Removes discardable tags like created_by on modified objects
79 */
80 lateUploadHooks.add(new DiscardTagsHook());
[1169]81 }
[230]82
[1808]83 /**
[2083]84 * Registers an upload hook. Adds the hook at the first position of the upload hooks.
[2512]85 *
[2081]86 * @param hook the upload hook. Ignored if null.
87 */
88 public static void registerUploadHook(UploadHook hook) {
[5497]89 registerUploadHook(hook, false);
90 }
91
92 /**
93 * Registers an upload hook. Adds the hook at the first position of the upload hooks.
94 *
95 * @param hook the upload hook. Ignored if null.
96 * @param late true, if the hook should be executed after the upload dialog
97 * has been confirmed. Late upload hooks should in general succeed and not
98 * abort the upload.
99 */
100 public static void registerUploadHook(UploadHook hook, boolean late) {
[8510]101 if (hook == null) return;
[5497]102 if (late) {
103 if (!lateUploadHooks.contains(hook)) {
104 lateUploadHooks.add(0, hook);
105 }
106 } else {
107 if (!uploadHooks.contains(hook)) {
108 uploadHooks.add(0, hook);
109 }
[2081]110 }
111 }
112
113 /**
114 * Unregisters an upload hook. Removes the hook from the list of upload hooks.
[2512]115 *
[2081]116 * @param hook the upload hook. Ignored if null.
117 */
118 public static void unregisterUploadHook(UploadHook hook) {
[8510]119 if (hook == null) return;
[2081]120 if (uploadHooks.contains(hook)) {
121 uploadHooks.remove(hook);
122 }
[5497]123 if (lateUploadHooks.contains(hook)) {
124 lateUploadHooks.remove(hook);
125 }
[2081]126 }
127
128 public UploadAction() {
[2317]129 super(tr("Upload data"), "upload", tr("Upload all changes in the active data layer to the OSM server"),
[4982]130 Shortcut.registerShortcut("file:upload", tr("File: {0}", tr("Upload data")), KeyEvent.VK_UP, Shortcut.CTRL_SHIFT), true);
[2323]131 putValue("help", ht("/Action/Upload"));
[2081]132 }
133
134 /**
[1808]135 * Refreshes the enabled state
[1811]136 *
[1808]137 */
[1820]138 @Override
139 protected void updateEnabledState() {
140 setEnabled(getEditLayer() != null);
[1808]141 }
142
[7402]143 public static boolean checkPreUploadConditions(AbstractModifiableLayer layer) {
[7358]144 return checkPreUploadConditions(layer,
[8510]145 layer instanceof OsmDataLayer ? new APIDataSet(((OsmDataLayer) layer).data) : null);
[2025]146 }
147
[5025]148 protected static void alertUnresolvedConflicts(OsmDataLayer layer) {
[2979]149 HelpAwareOptionPane.showOptionDialog(
150 Main.parent,
151 tr("<html>The data to be uploaded participates in unresolved conflicts of layer ''{0}''.<br>"
152 + "You have to resolve them first.</html>", layer.getName()
153 ),
154 tr("Warning"),
155 JOptionPane.WARNING_MESSAGE,
[9972]156 ht("/Action/Upload#PrimitivesParticipateInConflicts")
[2979]157 );
158 }
[6069]159
[5025]160 /**
[8931]161 * Warn user about discouraged upload, propose to cancel operation.
162 * @param layer incriminated layer
163 * @return true if the user wants to cancel, false if they want to continue
[5025]164 */
[7402]165 public static boolean warnUploadDiscouraged(AbstractModifiableLayer layer) {
[5233]166 return GuiHelper.warnUser(tr("Upload discouraged"),
167 "<html>" +
[5025]168 tr("You are about to upload data from the layer ''{0}''.<br /><br />"+
[5233]169 "Sending data from this layer is <b>strongly discouraged</b>. If you continue,<br />"+
170 "it may require you subsequently have to revert your changes, or force other contributors to.<br /><br />"+
171 "Are you sure you want to continue?", layer.getName())+
172 "</html>",
173 ImageProvider.get("upload"), tr("Ignore this hint and upload anyway"));
[5025]174 }
[2979]175
176 /**
177 * Check whether the preconditions are met to upload data in <code>apiData</code>.
[5025]178 * Makes sure upload is allowed, primitives in <code>apiData</code> don't participate in conflicts and
[5266]179 * runs the installed {@link UploadHook}s.
[3530]180 *
[2979]181 * @param layer the source layer of the data to be uploaded
182 * @param apiData the data to be uploaded
183 * @return true, if the preconditions are met; false, otherwise
184 */
[7402]185 public static boolean checkPreUploadConditions(AbstractModifiableLayer layer, APIDataSet apiData) {
[5025]186 if (layer.isUploadDiscouraged()) {
187 if (warnUploadDiscouraged(layer)) {
188 return false;
189 }
190 }
[7358]191 if (layer instanceof OsmDataLayer) {
192 OsmDataLayer osmLayer = (OsmDataLayer) layer;
193 ConflictCollection conflicts = osmLayer.getConflicts();
194 if (apiData.participatesInConflict(conflicts)) {
195 alertUnresolvedConflicts(osmLayer);
196 return false;
197 }
[2025]198 }
[2979]199 // Call all upload hooks in sequence.
200 // FIXME: this should become an asynchronous task
201 //
[7358]202 if (apiData != null) {
203 for (UploadHook hook : uploadHooks) {
204 if (!hook.checkUpload(apiData))
205 return false;
206 }
[3671]207 }
[2025]208
209 return true;
210 }
211
[2979]212 /**
213 * Uploads data to the OSM API.
[3530]214 *
[2979]215 * @param layer the source layer for the data to upload
216 * @param apiData the primitives to be added, updated, or deleted
217 */
[4414]218 public void uploadData(final OsmDataLayer layer, APIDataSet apiData) {
[2025]219 if (apiData.isEmpty()) {
[2005]220 JOptionPane.showMessageDialog(
[1857]221 Main.parent,
[2025]222 tr("No changes to upload."),
[1857]223 tr("Warning"),
[2025]224 JOptionPane.INFORMATION_MESSAGE
[1857]225 );
[1169]226 return;
227 }
[2250]228 if (!checkPreUploadConditions(layer, apiData))
[1169]229 return;
[2598]230
231 final UploadDialog dialog = UploadDialog.getUploadDialog();
[9514]232 dialog.setChangesetTags(layer.data);
[2598]233 dialog.setUploadedPrimitives(apiData);
234 dialog.setVisible(true);
[9462]235 dialog.rememberUserInput();
[2598]236 if (dialog.isCanceled())
237 return;
238
[5497]239 for (UploadHook hook : lateUploadHooks) {
240 if (!hook.checkUpload(apiData))
241 return;
242 }
243
[2040]244 Main.worker.execute(
[2569]245 new UploadPrimitivesTask(
246 UploadDialog.getUploadDialog().getUploadStrategySpecification(),
[2250]247 layer,
[2598]248 apiData,
249 UploadDialog.getUploadDialog().getChangeset()
[2040]250 )
251 );
[1663]252 }
253
[6084]254 @Override
[2250]255 public void actionPerformed(ActionEvent e) {
256 if (!isEnabled())
257 return;
258 if (Main.map == null) {
259 JOptionPane.showMessageDialog(
260 Main.parent,
261 tr("Nothing to upload. Get some data first."),
262 tr("Warning"),
263 JOptionPane.WARNING_MESSAGE
264 );
265 return;
266 }
267 APIDataSet apiData = new APIDataSet(Main.main.getCurrentDataSet());
[6336]268 uploadData(Main.main.getEditLayer(), apiData);
[2250]269 }
[230]270}
Note: See TracBrowser for help on using the repository browser.