source: josm/trunk/src/org/openstreetmap/josm/gui/io/AsynchronousUploadPrimitivesTask.java@ 14052

Last change on this file since 14052 was 14052, checked in by Don-vip, 6 years ago

see #16010 - use JMockit to enable more extensive test coverage (patch by ris, modified)

see https://github.com/openstreetmap/josm/pull/24/commits for details

  • Property svn:eol-style set to native
File size: 5.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.util.Optional;
7
8import javax.swing.JOptionPane;
9
10import org.openstreetmap.josm.data.APIDataSet;
11import org.openstreetmap.josm.data.osm.Changeset;
12import org.openstreetmap.josm.gui.MainApplication;
13import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
14import org.openstreetmap.josm.gui.layer.OsmDataLayer;
15import org.openstreetmap.josm.gui.progress.ProgressTaskId;
16import org.openstreetmap.josm.gui.util.GuiHelper;
17import org.openstreetmap.josm.io.UploadStrategySpecification;
18
19/**
20 * Task for uploading primitives using background worker threads. The actual upload is delegated to the
21 * {@link UploadPrimitivesTask}. This class is a wrapper over that to make the background upload process safe. There
22 * can only be one instance of this class, hence background uploads are limited to one at a time. This class also
23 * changes the editLayer of {@link org.openstreetmap.josm.gui.layer.MainLayerManager} to null during upload so that
24 * any changes to the uploading layer are prohibited.
25 *
26 * @author udit
27 * @since 13133
28 */
29public final class AsynchronousUploadPrimitivesTask extends UploadPrimitivesTask {
30
31 /**
32 * Static instance
33 */
34 private static AsynchronousUploadPrimitivesTask asynchronousUploadPrimitivesTask;
35
36 /**
37 * Member fields
38 */
39 private final ProgressTaskId taskId;
40 private final OsmDataLayer uploadDataLayer;
41
42 /**
43 * Private constructor to restrict creating more Asynchronous upload tasks
44 *
45 * @param uploadStrategySpecification UploadStrategySpecification for the DataLayer
46 * @param osmDataLayer Datalayer to be uploaded
47 * @param apiDataSet ApiDataSet that contains the primitives to be uploaded
48 * @param changeset Changeset for the datalayer
49 *
50 * @throws IllegalArgumentException if layer is null
51 * @throws IllegalArgumentException if toUpload is null
52 * @throws IllegalArgumentException if strategy is null
53 * @throws IllegalArgumentException if changeset is null
54 */
55 private AsynchronousUploadPrimitivesTask(UploadStrategySpecification uploadStrategySpecification,
56 OsmDataLayer osmDataLayer, APIDataSet apiDataSet, Changeset changeset) {
57 super(uploadStrategySpecification,
58 osmDataLayer,
59 apiDataSet,
60 changeset);
61
62 uploadDataLayer = osmDataLayer;
63 // Create a ProgressTaskId for background upload
64 taskId = new ProgressTaskId("core", "async-upload");
65 }
66
67 /**
68 * Creates an instance of AsynchronousUploadPrimitiveTask
69 *
70 * @param uploadStrategySpecification UploadStrategySpecification for the DataLayer
71 * @param dataLayer Datalayer to be uploaded
72 * @param apiDataSet ApiDataSet that contains the primitives to be uploaded
73 * @param changeset Changeset for the datalayer
74 * @return Returns an {@literal Optional<AsynchronousUploadPrimitivesTask> } if there is no
75 * background upload in progress. Otherwise returns an {@literal Optional.empty()}
76 *
77 * @throws IllegalArgumentException if layer is null
78 * @throws IllegalArgumentException if toUpload is null
79 * @throws IllegalArgumentException if strategy is null
80 * @throws IllegalArgumentException if changeset is null
81 */
82 public static Optional<AsynchronousUploadPrimitivesTask> createAsynchronousUploadTask(
83 UploadStrategySpecification uploadStrategySpecification,
84 OsmDataLayer dataLayer, APIDataSet apiDataSet, Changeset changeset) {
85 synchronized (AsynchronousUploadPrimitivesTask.class) {
86 if (asynchronousUploadPrimitivesTask != null) {
87 GuiHelper.runInEDTAndWait(() ->
88 JOptionPane.showMessageDialog(MainApplication.parent,
89 tr("A background upload is already in progress. " +
90 "Kindly wait for it to finish before uploading new changes")));
91 return Optional.empty();
92 } else {
93 // Create an asynchronous upload task
94 asynchronousUploadPrimitivesTask = new AsynchronousUploadPrimitivesTask(
95 uploadStrategySpecification,
96 dataLayer,
97 apiDataSet,
98 changeset);
99 return Optional.ofNullable(asynchronousUploadPrimitivesTask);
100 }
101 }
102 }
103
104 /**
105 * Get the current upload task
106 * @return {@literal Optional<AsynchronousUploadPrimitivesTask> }
107 */
108 public static Optional<AsynchronousUploadPrimitivesTask> getCurrentAsynchronousUploadTask() {
109 return Optional.ofNullable(asynchronousUploadPrimitivesTask);
110 }
111
112 @Override
113 public ProgressTaskId canRunInBackground() {
114 return taskId;
115 }
116
117 @Override
118 protected void realRun() {
119 // Lock the data layer before upload in EDT
120 GuiHelper.runInEDTAndWait(() -> {
121 // Remove the commands from the undo stack
122 MainApplication.undoRedo.clean(uploadDataLayer.getDataSet());
123 MainApplication.getLayerManager().prepareLayerForUpload(uploadDataLayer);
124
125 // Repainting the Layer List dialog to update the icon of the active layer
126 LayerListDialog.getInstance().repaint();
127 });
128 super.realRun();
129 }
130
131 @Override
132 protected void cancel() {
133 super.cancel();
134 asynchronousUploadPrimitivesTask = null;
135 }
136
137 @Override
138 protected void finish() {
139 try {
140 // Unlock the data layer in EDT
141 GuiHelper.runInEDTAndWait(() -> {
142 MainApplication.getLayerManager().processLayerAfterUpload(uploadDataLayer);
143 LayerListDialog.getInstance().repaint();
144 });
145 super.finish();
146 } finally {
147 asynchronousUploadPrimitivesTask = null;
148 }
149 }
150}
Note: See TracBrowser for help on using the repository browser.