source: josm/trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java@ 2474

Last change on this file since 2474 was 2471, checked in by Gubaer, 14 years ago

fixed #3963: Synchronize does not work

File size: 9.3 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.awt.event.KeyEvent;
9import java.io.IOException;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.logging.Logger;
13
14import javax.swing.JOptionPane;
15
16import org.openstreetmap.josm.Main;
17import org.openstreetmap.josm.data.osm.DataSet;
18import org.openstreetmap.josm.data.osm.DataSetMerger;
19import org.openstreetmap.josm.data.osm.Node;
20import org.openstreetmap.josm.data.osm.OsmPrimitive;
21import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
22import org.openstreetmap.josm.data.osm.Relation;
23import org.openstreetmap.josm.data.osm.Way;
24import org.openstreetmap.josm.gui.ExceptionDialogUtil;
25import org.openstreetmap.josm.gui.PleaseWaitRunnable;
26import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
27import org.openstreetmap.josm.gui.progress.ProgressMonitor;
28import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
29import org.openstreetmap.josm.io.OsmServerObjectReader;
30import org.openstreetmap.josm.io.OsmTransferException;
31import org.openstreetmap.josm.tools.Shortcut;
32import org.xml.sax.SAXException;
33
34/**
35 * This action synchronizes a set of primitives with their state on the server.
36 *
37 */
38public class UpdateSelectionAction extends JosmAction {
39
40 /**
41 * handle an exception thrown because a primitive was deleted on the server
42 *
43 * @param id the primitive id
44 */
45 protected void handlePrimitiveGoneException(long id, OsmPrimitiveType type) {
46 MultiFetchServerObjectReader reader = new MultiFetchServerObjectReader();
47 reader.append(getCurrentDataSet(),id, type);
48 DataSet ds = null;
49 try {
50 ds = reader.parseOsm(NullProgressMonitor.INSTANCE);
51 } catch(Exception e) {
52 ExceptionDialogUtil.explainException(e);
53 }
54 Main.map.mapView.getEditLayer().mergeFrom(ds);
55 }
56
57 /**
58 * Updates the data for for the {@see OsmPrimitive}s in <code>selection</code>
59 * with the data currently kept on the server.
60 *
61 * @param selection a collection of {@see OsmPrimitive}s to update
62 *
63 */
64 public void updatePrimitives(final Collection<OsmPrimitive> selection) {
65 UpdatePrimitivesTask task = new UpdatePrimitivesTask(selection);
66 Main.worker.submit(task);
67 }
68
69 /**
70 * Updates the data for the {@see OsmPrimitive}s with id <code>id</code>
71 * with the data currently kept on the server.
72 *
73 * @param id the id of a primitive in the {@see DataSet} of the current edit layer
74 * @exception IllegalStateException thrown if there is no primitive with <code>id</code> in
75 * the current dataset
76 * @exception IllegalStateException thrown if there is no current dataset
77 *
78 */
79 public void updatePrimitive(OsmPrimitiveType type, long id) throws IllegalStateException{
80 if (getEditLayer() == null)
81 throw new IllegalStateException(tr("No current dataset found"));
82 OsmPrimitive primitive = getEditLayer().data.getPrimitiveById(id, type);
83 if (primitive == null)
84 throw new IllegalStateException(tr("Didn''t find an object with id {0} in the current dataset", id));
85 updatePrimitives(Collections.singleton(primitive));
86 }
87
88 /**
89 * constructor
90 */
91 public UpdateSelectionAction() {
92 super(tr("Update selection"),
93 "updateselection",
94 tr("Updates the currently selected objects from the server (re-downloads data)"),
95 Shortcut.registerShortcut("file:updateselection",
96 tr("Update Selection"),
97 KeyEvent.VK_U,
98 Shortcut.GROUP_HOTKEY + Shortcut.GROUPS_ALT2),
99 true);
100 putValue("help", ht("UpdateSelection"));
101 }
102
103 @Override
104 protected void updateEnabledState() {
105 if (getCurrentDataSet() == null) {
106 setEnabled(false);
107 } else {
108 updateEnabledState(getCurrentDataSet().getSelected());
109 }
110 }
111
112 @Override
113 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
114 setEnabled(selection != null && !selection.isEmpty());
115 }
116
117 /**
118 * action handler
119 */
120 public void actionPerformed(ActionEvent e) {
121 if (! isEnabled())
122 return;
123 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
124 if (selection.size() == 0) {
125 JOptionPane.showMessageDialog(
126 Main.parent,
127 tr("There are no selected objects to update."),
128 tr("Selection empty"),
129 JOptionPane.INFORMATION_MESSAGE
130 );
131 return;
132 }
133 updatePrimitives(selection);
134 }
135
136 /**
137 * The asynchronous task for updating the data using multi fetch.
138 *
139 */
140 static class UpdatePrimitivesTask extends PleaseWaitRunnable {
141 static private final Logger logger = Logger.getLogger(UpdatePrimitivesTask.class.getName());
142
143 private DataSet ds;
144 private boolean canceled;
145 private Exception lastException;
146 private Collection<? extends OsmPrimitive> toUpdate;
147 private MultiFetchServerObjectReader reader;
148
149 /**
150 *
151 * @param toUpdate a collection of primitives to update from the server
152 */
153 public UpdatePrimitivesTask(Collection<? extends OsmPrimitive> toUpdate) {
154 super(tr("Update objects"), false /* don't ignore exception*/);
155 canceled = false;
156 this.toUpdate = toUpdate;
157 }
158
159 @Override
160 protected void cancel() {
161 canceled = true;
162 if (reader != null) {
163 reader.cancel();
164 }
165 }
166
167 @Override
168 protected void finish() {
169 if (canceled)
170 return;
171 if (lastException != null) {
172 ExceptionDialogUtil.explainException(lastException);
173 return;
174 }
175 if (ds != null && Main.main.getEditLayer() != null) {
176 Main.main.getEditLayer().mergeFrom(ds);
177 Main.main.getEditLayer().onPostDownloadFromServer();
178 }
179 }
180
181 protected void initMultiFetchReaderWithNodes(MultiFetchServerObjectReader reader) {
182 for (OsmPrimitive primitive : toUpdate) {
183 if (primitive instanceof Node && !primitive.isNew()) {
184 reader.append((Node)primitive);
185 } else if (primitive instanceof Way) {
186 Way way = (Way)primitive;
187 for (Node node: way.getNodes()) {
188 if (!node.isNew()) {
189 reader.append(node);
190 }
191 }
192 }
193 }
194 }
195
196 protected void initMultiFetchReaderWithWays(MultiFetchServerObjectReader reader) {
197 for (OsmPrimitive primitive : toUpdate) {
198 if (primitive instanceof Way && !primitive.isNew()) {
199 reader.append((Way)primitive);
200 }
201 }
202 }
203
204 protected void initMultiFetchReaderWithRelations(MultiFetchServerObjectReader reader) {
205 for (OsmPrimitive primitive : toUpdate) {
206 if (primitive instanceof Relation && !primitive.isNew()) {
207 reader.append((Relation)primitive);
208 }
209 }
210 }
211
212
213 @Override
214 protected void realRun() throws SAXException, IOException, OsmTransferException {
215 progressMonitor.indeterminateSubTask("");
216 this.ds = new DataSet();
217 DataSet theirDataSet;
218 try {
219 reader = new MultiFetchServerObjectReader();
220 initMultiFetchReaderWithNodes(reader);
221 initMultiFetchReaderWithWays(reader);
222 initMultiFetchReaderWithRelations(reader);
223 theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
224 DataSetMerger merger = new DataSetMerger(ds, theirDataSet);
225 merger.merge();
226 // a way loaded with MultiFetch may be incomplete because at least one of its
227 // nodes isn't present in the local data set. We therefore fully load all
228 // incomplete ways.
229 //
230 for (Way w : ds.getWays()) {
231 if (w.incomplete) {
232 OsmServerObjectReader reader = new OsmServerObjectReader(w.getId(), OsmPrimitiveType.WAY, true /* full */);
233 theirDataSet = reader.parseOsm(progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false));
234 merger = new DataSetMerger(ds, theirDataSet);
235 merger.merge();
236 }
237 }
238 } catch(Exception e) {
239 if (canceled)
240 return;
241 lastException = e;
242 }
243 }
244 }
245}
Note: See TracBrowser for help on using the repository browser.