Ticket #8509: async_v2.patch
| File async_v2.patch, 13.4 KB (added by , 8 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/UploadAction.java
9 9 import java.util.LinkedList; 10 10 import java.util.List; 11 11 import java.util.Map; 12 import java.util.Optional; 12 13 13 14 import javax.swing.JOptionPane; 14 15 … … 24 25 import org.openstreetmap.josm.data.osm.Changeset; 25 26 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 26 27 import org.openstreetmap.josm.gui.MainApplication; 28 import org.openstreetmap.josm.gui.io.AsynchronousUploadPrimitivesTask; 27 29 import org.openstreetmap.josm.gui.io.UploadDialog; 28 import org.openstreetmap.josm.gui.io.UploadPrimitivesTask;29 30 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 30 31 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 31 32 import org.openstreetmap.josm.gui.util.GuiHelper; … … 257 258 hook.modifyChangesetTags(changesetTags); 258 259 } 259 260 260 MainApplication.worker.execute( 261 new UploadPrimitivesTask( 262 UploadDialog.getUploadDialog().getUploadStrategySpecification(), 263 layer, 264 apiData, 265 cs 266 ) 267 ); 261 Optional <AsynchronousUploadPrimitivesTask> asyncUploadTask = AsynchronousUploadPrimitivesTask.createAsynchronousUploadTask( 262 UploadDialog.getUploadDialog().getUploadStrategySpecification(), 263 layer, 264 apiData, 265 cs); 266 267 if (asyncUploadTask.isPresent()) { 268 MainApplication.worker.execute(asyncUploadTask.get()); 269 } 268 270 } 269 271 270 272 @Override -
src/org/openstreetmap/josm/gui/io/AsynchronousUploadPrimitivesTask.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.io; 3 4 import org.openstreetmap.josm.data.APIDataSet; 5 import org.openstreetmap.josm.data.osm.Changeset; 6 import org.openstreetmap.josm.gui.MainApplication; 7 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 8 import org.openstreetmap.josm.gui.progress.ProgressTaskId; 9 import org.openstreetmap.josm.gui.util.GuiHelper; 10 import org.openstreetmap.josm.io.UploadStrategySpecification; 11 import org.openstreetmap.josm.tools.I18n; 12 13 import javax.swing.*; 14 import java.awt.*; 15 import java.util.Optional; 16 17 /** 18 * Task for uploading primitives using background worker threads 19 * @author udit 20 */ 21 public class AsynchronousUploadPrimitivesTask extends UploadPrimitivesTask { 22 23 /** 24 * Static instance 25 */ 26 private static AsynchronousUploadPrimitivesTask asynchronousUploadPrimitivesTask = null; 27 28 /** 29 * Member fields 30 */ 31 private final ProgressTaskId taskId; 32 private final OsmDataLayer uploadDataLayer; 33 34 /** 35 * Private constructor to restrict creating more Asynchronous upload tasks 36 * 37 * @param uploadStrategySpecification 38 * @param osmDataLayer 39 * @param apiDataSet 40 * @param changeset 41 */ 42 private AsynchronousUploadPrimitivesTask(UploadStrategySpecification uploadStrategySpecification, OsmDataLayer osmDataLayer, APIDataSet apiDataSet, Changeset changeset) { 43 super(uploadStrategySpecification, 44 osmDataLayer, 45 apiDataSet, 46 changeset); 47 48 uploadDataLayer = osmDataLayer; 49 // Create a ProgressTaskId for background upload 50 taskId = new ProgressTaskId("core", "async-upload"); 51 } 52 53 /** 54 * Creates an instance of AsynchronousUploadPrimitiveTask 55 * 56 * @param uploadStrategySpecification 57 * @param dataLayer 58 * @param apiDataSet 59 * @param changeset 60 * @return Optional<AsynchronousUploadPrimitivesTask> 61 */ 62 public static Optional<AsynchronousUploadPrimitivesTask> createAsynchronousUploadTask 63 (UploadStrategySpecification uploadStrategySpecification, 64 OsmDataLayer dataLayer, APIDataSet apiDataSet, Changeset changeset) { 65 synchronized (AsynchronousUploadPrimitivesTask.class) { 66 if (asynchronousUploadPrimitivesTask != null) { 67 if (!GraphicsEnvironment.isHeadless()) { 68 GuiHelper.runInEDTAndWait(() -> 69 JOptionPane.showMessageDialog(MainApplication.parent, 70 I18n.tr("A background upload is already in progress. Kindly wait for it to finish before uploading new changes"))); 71 } 72 return Optional.empty(); 73 } else { 74 // Create an asynchronous upload task 75 asynchronousUploadPrimitivesTask = new AsynchronousUploadPrimitivesTask( 76 uploadStrategySpecification, 77 dataLayer, 78 apiDataSet, 79 changeset); 80 return Optional.ofNullable(asynchronousUploadPrimitivesTask); 81 } 82 } 83 } 84 85 /** 86 * Get the current upload task 87 * @return Optional<AsynchronousUploadPrimitivesTask> 88 */ 89 public static Optional<AsynchronousUploadPrimitivesTask> getCurrentAsynchronousUploadTask () { 90 return Optional.ofNullable(asynchronousUploadPrimitivesTask); 91 } 92 93 @Override 94 public ProgressTaskId canRunInBackground() { 95 return taskId; 96 } 97 98 @Override 99 protected void realRun() { 100 // Lock the data layer before upload in EDT 101 GuiHelper.runInEDTAndWait(() -> uploadDataLayer.setReadOnly()); 102 super.realRun(); 103 } 104 105 @Override 106 protected void cancel() { 107 super.cancel(); 108 asynchronousUploadPrimitivesTask = null; 109 } 110 111 @Override 112 protected void finish() { 113 try { 114 // Unlock the data layer in EDT 115 GuiHelper.runInEDTAndWait(() -> uploadDataLayer.unsetReadOnly()); 116 super.finish(); 117 } finally { 118 asynchronousUploadPrimitivesTask = null; 119 } 120 } 121 } 122 No newline at end of file -
src/org/openstreetmap/josm/gui/layer/MainLayerManager.java
1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.gui.layer; 3 3 4 import org.openstreetmap.josm.data.osm.DataSet; 5 import org.openstreetmap.josm.gui.MainApplication; 6 import org.openstreetmap.josm.gui.util.GuiHelper; 7 8 import javax.swing.*; 4 9 import java.util.ArrayList; 5 10 import java.util.Collection; 6 11 import java.util.List; … … 7 12 import java.util.ListIterator; 8 13 import java.util.concurrent.CopyOnWriteArrayList; 9 14 10 import org.openstreetmap.josm.data.osm.DataSet; 11 import org.openstreetmap.josm.gui.util.GuiHelper; 15 import static org.openstreetmap.josm.tools.I18n.tr; 12 16 13 17 /** 14 18 * This class extends the layer manager by adding an active and an edit layer. … … 205 209 } 206 210 207 211 /** 208 * Set the active layer. If the layer is an OsmDataLayer, the edit layer is also changed. 212 * Set the active layer iff the layer is not read only. 213 * If the layer is an OsmDataLayer, the edit layer is also changed. 209 214 * @param layer The active layer. 210 215 */ 211 216 public void setActiveLayer(final Layer layer) { 212 217 // we force this on to the EDT Thread to make events fire from there. 213 218 // The synchronization lock needs to be held by the EDT. 214 GuiHelper.runInEDTAndWaitWithException(() -> realSetActiveLayer(layer)); 219 if (layer instanceof OsmDataLayer && ((OsmDataLayer) layer).isReadOnly()) { 220 GuiHelper.runInEDT(() -> 221 JOptionPane.showMessageDialog( 222 MainApplication.parent, 223 tr("Trying to set a read only data layer as edit layer"), 224 tr("Warning"), 225 JOptionPane.WARNING_MESSAGE)); 226 } else { 227 GuiHelper.runInEDTAndWaitWithException(() -> realSetActiveLayer(layer)); 228 } 215 229 } 216 230 217 231 protected synchronized void realSetActiveLayer(final Layer layer) { … … 309 323 * @return the currently active layer (may be null) 310 324 */ 311 325 public synchronized Layer getActiveLayer() { 312 return activeLayer; 326 if (activeLayer instanceof OsmDataLayer) { 327 if (!((OsmDataLayer)activeLayer).isReadOnly()) { 328 return activeLayer; 329 } else { 330 return null; 331 } 332 } else { 333 return activeLayer; 334 } 313 335 } 314 336 315 337 /** … … 318 340 * @return the current edit layer. May be null. 319 341 */ 320 342 public synchronized OsmDataLayer getEditLayer() { 321 return editLayer; 343 if (editLayer != null && !editLayer.isReadOnly()) 344 return editLayer; 345 else 346 return null; 322 347 } 323 348 324 349 /** … … 326 351 * @return That data set, <code>null</code> if there is no edit layer. 327 352 */ 328 353 public synchronized DataSet getEditDataSet() { 329 if (editLayer != null ) {354 if (editLayer != null && !editLayer.isReadOnly()) { 330 355 return editLayer.data; 331 356 } else { 332 357 return null; -
src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
32 32 import java.util.Set; 33 33 import java.util.concurrent.CopyOnWriteArrayList; 34 34 import java.util.concurrent.atomic.AtomicInteger; 35 import java.util.concurrent.locks.ReentrantReadWriteLock; 35 36 import java.util.regex.Pattern; 36 37 37 38 import javax.swing.AbstractAction; … … 129 130 130 131 private boolean requiresSaveToFile; 131 132 private boolean requiresUploadToServer; 133 private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 132 134 133 135 /** 134 136 * List of validation errors in this layer. … … 1142 1144 } 1143 1145 super.setName(name); 1144 1146 } 1147 1148 public void setReadOnly() { 1149 lock.writeLock().lock(); 1150 } 1151 1152 public void unsetReadOnly() { 1153 lock.writeLock().unlock(); 1154 } 1155 1156 public boolean isReadOnly() { 1157 return lock.isWriteLocked(); 1158 } 1145 1159 } -
test/unit/org/openstreetmap/josm/gui/io/AsynchronousUploadPrimitivesTaskTest.java
1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.io; 3 4 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 5 import org.junit.*; 6 import org.openstreetmap.josm.data.APIDataSet; 7 import org.openstreetmap.josm.data.coor.LatLon; 8 import org.openstreetmap.josm.data.osm.Changeset; 9 import org.openstreetmap.josm.data.osm.DataSet; 10 import org.openstreetmap.josm.data.osm.Node; 11 import org.openstreetmap.josm.data.osm.Way; 12 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 13 import org.openstreetmap.josm.io.UploadStrategySpecification; 14 import org.openstreetmap.josm.testutils.JOSMTestRules; 15 16 import java.util.Optional; 17 18 public class AsynchronousUploadPrimitivesTaskTest { 19 20 private UploadStrategySpecification strategy; 21 private OsmDataLayer layer; 22 private APIDataSet toUpload; 23 private Changeset changeset; 24 private AsynchronousUploadPrimitivesTask uploadPrimitivesTask; 25 26 /** 27 * Setup tests 28 */ 29 @Rule 30 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 31 public JOSMTestRules test = new JOSMTestRules(); 32 33 @Before 34 public void bootStrap() { 35 DataSet dataSet = new DataSet(); 36 Node node1 = new Node(); 37 Node node2 = new Node(); 38 node1.setCoor(new LatLon(0, 0)); 39 node2.setCoor(new LatLon(30, 30)); 40 Way way = new Way(); 41 way.addNode(node1); 42 way.addNode(node2); 43 dataSet.addPrimitive(node1); 44 dataSet.addPrimitive(node2); 45 dataSet.addPrimitive(way); 46 47 toUpload = new APIDataSet(dataSet); 48 layer = new OsmDataLayer(dataSet, "uploadTest", null); 49 strategy = new UploadStrategySpecification(); 50 changeset = new Changeset(); 51 uploadPrimitivesTask = AsynchronousUploadPrimitivesTask.createAsynchronousUploadTask(strategy, layer, toUpload, changeset).get(); 52 } 53 54 @After 55 public void tearDown () { 56 toUpload = null; 57 layer = null; 58 strategy = null; 59 changeset = null; 60 uploadPrimitivesTask = null; 61 } 62 63 @Test 64 public void testSingleUploadInstance () { 65 Optional<AsynchronousUploadPrimitivesTask> task = AsynchronousUploadPrimitivesTask.createAsynchronousUploadTask(strategy, layer, toUpload, changeset); 66 Assert.assertNotNull(uploadPrimitivesTask); 67 Assert.assertFalse(task.isPresent()); 68 } 69 }
