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

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

fixed #3908: Exception when updating a way
fixed a few I18n issues

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