- Timestamp:
- 2012-01-18T19:48:23+01:00 (13 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/HelpAwareOptionPane.java
r3501 r4816 13 13 import java.util.List; 14 14 15 import javax.swing.AbstractAction; 16 import javax.swing.Action; 17 import javax.swing.Icon; 18 import javax.swing.JButton; 19 import javax.swing.JComponent; 20 import javax.swing.JDialog; 21 import javax.swing.JLabel; 22 import javax.swing.JOptionPane; 23 import javax.swing.KeyStroke; 24 import javax.swing.SwingUtilities; 15 import javax.swing.*; 25 16 26 17 import org.openstreetmap.josm.gui.help.HelpBrowser; … … 167 158 168 159 if (msg instanceof String) { 169 msg = new JLabel((String)msg); 160 JEditorPane pane = new JEditorPane(); 161 pane.setContentType("text/html"); 162 pane.setText((String) msg); 163 pane.setEditable(false); 164 pane.setOpaque(false); 165 msg = pane; 170 166 } 171 167 -
trunk/src/org/openstreetmap/josm/gui/io/AbstractUploadTask.java
r4191 r4816 8 8 import java.net.HttpURLConnection; 9 9 import java.text.SimpleDateFormat; 10 import java.util.Arrays; 11 import java.util.Collection; 10 12 import java.util.Collections; 11 13 import java.util.Date; … … 31 33 import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException; 32 34 import org.openstreetmap.josm.tools.DateUtils; 35 import org.openstreetmap.josm.tools.ExceptionUtil; 33 36 import org.openstreetmap.josm.tools.ImageProvider; 37 import org.openstreetmap.josm.tools.Pair; 34 38 35 39 public abstract class AbstractUploadTask extends PleaseWaitRunnable { … … 206 210 * a non-deleted way on the server. 207 211 */ 208 protected void handleUpload ConflictForNodeStillInUse(long nodeId, long wayId) {212 protected void handleUploadPreconditionFailedConflict(OsmApiException e, Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict) { 209 213 ButtonSpec[] options = new ButtonSpec[] { 210 214 new ButtonSpec( 211 215 tr("Prepare conflict resolution"), 212 216 ImageProvider.get("ok"), 213 tr("Click to download all parent ways for node {0}", nodeId),217 tr("Click to download all referring objects for {0}", conflict.a), 214 218 null /* no specific help context */ 215 219 ), … … 217 221 tr("Cancel"), 218 222 ImageProvider.get("cancel"), 219 tr("Click to cancel and to resume editing the map" , nodeId),223 tr("Click to cancel and to resume editing the map"), 220 224 null /* no specific help context */ 221 225 ) 222 226 }; 223 String msg = tr("<html>Uploading <strong>failed</strong> because you tried " 224 + "to delete node {0} which is still in use in way {1}.<br><br>" 225 + "Click <strong>{2}</strong> to download all parent ways of node {0}.<br>" 226 + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog." 227 + "</html>", 228 nodeId, wayId, options[0].text 229 ); 230 227 String msg = ExceptionUtil.explainPreconditionFailed(e).replace("</html>", "<br><br>" + tr( 228 "Click <strong>{0}</strong> to load them now.<br>" 229 + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog.", 230 options[0].text)) + "</html>"; 231 231 int ret = HelpAwareOptionPane.showOptionDialog( 232 232 Main.parent, 233 233 msg, 234 tr(" Nodestill in use"),234 tr("Object still in use"), 235 235 JOptionPane.ERROR_MESSAGE, 236 236 null, … … 238 238 options[0], 239 239 "/Action/Upload#NodeStillInUseInWay" 240 ); 241 if (ret != 0) return; 242 DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), nodeId, OsmPrimitiveType.NODE); 240 ); 241 if (ret == 0) { 242 DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), Arrays.asList(conflict.a)); 243 } 243 244 } 244 245 … … 263 264 return; 264 265 } 265 pattern = "Node (\\d+) is still used by way (\\d+).";266 p = Pattern.compile(pattern);267 m = p.matcher(e.getErrorHeader());268 if (m.matches()) {269 handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));270 return;271 }272 266 System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader())); 273 267 handleUploadConflictForUnknownConflict(); … … 280 274 */ 281 275 protected void handlePreconditionFailed(OsmApiException e) { 282 String pattern = "Precondition failed: Node (\\d+) is still used by way (\\d+)."; 283 Pattern p = Pattern.compile(pattern); 284 Matcher m = p.matcher(e.getErrorHeader()); 285 if (m.matches()) { 286 handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2))); 287 return; 288 } 289 System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader())); 290 ExceptionDialogUtil.explainPreconditionFailed(e); 276 // in the worst case, ExceptionUtil.parsePreconditionFailed is executed trice - should not be too expensive 277 Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict = ExceptionUtil.parsePreconditionFailed(e.getErrorHeader()); 278 if (conflict != null) { 279 handleUploadPreconditionFailedConflict(e, conflict); 280 } else { 281 System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader())); 282 ExceptionDialogUtil.explainPreconditionFailed(e); 283 } 291 284 } 292 285 -
trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java
r4703 r4816 23 23 24 24 import org.openstreetmap.josm.Main; 25 import org.openstreetmap.josm.data.osm.Node; 26 import org.openstreetmap.josm.data.osm.OsmPrimitive; 27 import org.openstreetmap.josm.data.osm.Relation; 28 import org.openstreetmap.josm.data.osm.Way; 25 29 import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder; 26 30 import org.openstreetmap.josm.io.ChangesetClosedException; … … 33 37 import org.openstreetmap.josm.io.auth.CredentialsManager; 34 38 39 @SuppressWarnings("CallToThreadDumpStack") 35 40 public class ExceptionUtil { 36 41 private ExceptionUtil() { … … 46 51 String msg = tr( 47 52 "<html>Failed to initialize communication with the OSM server {0}.<br>" 48 + "Check the server URL in your preferences and your internet connection. </html>", Main.pref.get(53 + "Check the server URL in your preferences and your internet connection.", Main.pref.get( 49 54 "osm-server.url", "http://api.openstreetmap.org/api")); 50 55 return msg; … … 70 75 } 71 76 72 /** 73 * Explains a precondition exception when a child relation could not be deleted because 74 * it is still referred to by an undeleted parent relation. 75 * 76 * @param e the exception 77 * @param childRelation the child relation 78 * @param parentRelation the parent relation 79 * @return 80 */ 81 public static String explainDeletedRelationStillInUse(OsmApiException e, long childRelation, long parentRelation) { 82 String msg = tr( 83 "<html><strong>Failed</strong> to delete <strong>relation {0}</strong>." 84 + " It is still referred to by relation {1}.<br>" 85 + "Please load relation {1}, remove the reference to relation {0}, and upload again.</html>", 86 childRelation,parentRelation 87 ); 88 return msg; 89 } 90 91 /** 92 * Explains a precondition exception when a child node could not be deleted because 93 * it is still referred to by undeleted parent ways. 94 * 95 * @param e the exception 96 * @param childNode the child node 97 * @param parentWays the parent ways 98 * @return 99 */ 100 public static String explainDeletedNodeStillInUse(OsmApiException e, long childNode, Collection<Long> parentWays) { 101 String ids = parentWays.size() == 1 ? parentWays.iterator().next().toString() : parentWays.toString(); 102 String msg = trn( 103 "<html><strong>Failed</strong> to delete <strong>node {0}</strong>." 104 + " It is still referred to by way {1}.<br>" 105 + "Please load the way, remove the reference to the node, and upload again.</html>", 106 "<html><strong>Failed</strong> to delete <strong>node {0}</strong>." 107 + " It is still referred to by ways {1}.<br>" 108 + "Please load the ways, remove the reference to the node, and upload again.</html>", 109 parentWays.size(), childNode, ids 110 ); 111 return msg; 77 public static Pair<OsmPrimitive, Collection<OsmPrimitive>> parsePreconditionFailed(String msg) { 78 final String ids = "(\\d+(?:,\\d+)*)"; 79 final Collection<OsmPrimitive> refs = new TreeSet<OsmPrimitive>(); // error message can contain several times the same way 80 Matcher m; 81 m = Pattern.compile(".*Node (\\d+) is still used by relations " + ids + ".*").matcher(msg); 82 if (m.matches()) { 83 OsmPrimitive n = new Node(Long.parseLong(m.group(1))); 84 for (String s : m.group(2).split(",")) { 85 refs.add(new Relation(Long.parseLong(m.group(2)))); 86 } 87 return Pair.create(n, refs); 88 } 89 m = Pattern.compile(".*Node (\\d+) is still used by ways " + ids + ".*").matcher(msg); 90 if (m.matches()) { 91 OsmPrimitive n = new Node(Long.parseLong(m.group(1))); 92 for (String s : m.group(2).split(",")) { 93 refs.add(new Way(Long.parseLong(m.group(2)))); 94 } 95 return Pair.create(n, refs); 96 } 97 m = Pattern.compile(".*The relation (\\d+) is used in relations? " + ids + ".*").matcher(msg); 98 if (m.matches()) { 99 OsmPrimitive n = new Relation(Long.parseLong(m.group(1))); 100 for (String s : m.group(2).split(",")) { 101 refs.add(new Relation(Long.parseLong(m.group(2)))); 102 } 103 return Pair.create(n, refs); 104 } 105 m = Pattern.compile(".*Way (\\d+) is still used by relations " + ids + ".*").matcher(msg); 106 if (m.matches()) { 107 OsmPrimitive n = new Way(Long.parseLong(m.group(1))); 108 for (String s : m.group(2).split(",")) { 109 refs.add(new Relation(Long.parseLong(m.group(2)))); 110 } 111 return Pair.create(n, refs); 112 } 113 m = Pattern.compile(".*Way (\\d+) requires the nodes with id in " + ids + ".*").matcher(msg); // ... ", which either do not exist, or are not visible" 114 if (m.matches()) { 115 OsmPrimitive n = new Way(Long.parseLong(m.group(1))); 116 for (String s : m.group(2).split(",")) { 117 refs.add(new Node(Long.parseLong(m.group(2)))); 118 } 119 return Pair.create(n, refs); 120 } 121 return null; 112 122 } 113 123 … … 120 130 e.printStackTrace(); 121 131 String msg = e.getErrorHeader(); 122 if (msg != null) { 123 Matcher m = Pattern.compile("Precondition failed: The relation (\\d+) is used in relation (\\d+)\\.").matcher(msg); 124 if (m.matches()) { 125 long childRelation = Long.parseLong(m.group(1)); 126 long parentRelation = Long.parseLong(m.group(2)); 127 return explainDeletedRelationStillInUse(e, childRelation, parentRelation); 132 Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict = parsePreconditionFailed(e.getErrorHeader()); 133 if (conflict != null) { 134 OsmPrimitive firstRefs = conflict.b.iterator().next(); 135 Long objId = conflict.a.getId(); 136 Collection<Long> refIds= Utils.transform(conflict.b, new Utils.Function<OsmPrimitive, Long>() { 137 138 @Override 139 public Long apply(OsmPrimitive x) { 140 return x.getId(); 141 } 142 }); 143 String refIdsString = refIds.size() == 1 ? refIds.iterator().next().toString() : refIds.toString(); 144 if (conflict.a instanceof Node) { 145 if (firstRefs instanceof Node) { 146 return "<html>" + trn( 147 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 148 + " It is still referred to by node {1}.<br>" 149 + "Please load the node, remove the reference to the node, and upload again.", 150 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 151 + " It is still referred to by nodes {1}.<br>" 152 + "Please load the nodes, remove the reference to the node, and upload again.", 153 conflict.b.size(), objId, refIdsString) + "</html>"; 154 } else if (firstRefs instanceof Way) { 155 return "<html>" + trn( 156 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 157 + " It is still referred to by way {1}.<br>" 158 + "Please load the way, remove the reference to the node, and upload again.", 159 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 160 + " It is still referred to by ways {1}.<br>" 161 + "Please load the ways, remove the reference to the node, and upload again.", 162 conflict.b.size(), objId, refIdsString) + "</html>"; 163 } else if (firstRefs instanceof Relation) { 164 return "<html>" + trn( 165 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 166 + " It is still referred to by relation {1}.<br>" 167 + "Please load the relation, remove the reference to the node, and upload again.", 168 "<strong>Failed</strong> to delete <strong>node {0}</strong>." 169 + " It is still referred to by relations {1}.<br>" 170 + "Please load the relations, remove the reference to the node, and upload again.", 171 conflict.b.size(), objId, refIdsString) + "</html>"; 172 } else { 173 throw new IllegalStateException(); 174 } 175 } else if (conflict.a instanceof Way) { 176 if (firstRefs instanceof Node) { 177 return "<html>" + trn( 178 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 179 + " It is still referred to by node {1}.<br>" 180 + "Please load the node, remove the reference to the way, and upload again.", 181 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 182 + " It is still referred to by nodes {1}.<br>" 183 + "Please load the nodes, remove the reference to the way, and upload again.", 184 conflict.b.size(), objId, refIdsString) + "</html>"; 185 } else if (firstRefs instanceof Way) { 186 return "<html>" + trn( 187 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 188 + " It is still referred to by way {1}.<br>" 189 + "Please load the way, remove the reference to the way, and upload again.", 190 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 191 + " It is still referred to by ways {1}.<br>" 192 + "Please load the ways, remove the reference to the way, and upload again.", 193 conflict.b.size(), objId, refIdsString) + "</html>"; 194 } else if (firstRefs instanceof Relation) { 195 return "<html>" + trn( 196 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 197 + " It is still referred to by relation {1}.<br>" 198 + "Please load the relation, remove the reference to the way, and upload again.", 199 "<strong>Failed</strong> to delete <strong>way {0}</strong>." 200 + " It is still referred to by relations {1}.<br>" 201 + "Please load the relations, remove the reference to the way, and upload again.", 202 conflict.b.size(), objId, refIdsString) + "</html>"; 203 } else { 204 throw new IllegalStateException(); 205 } 206 } else if (conflict.a instanceof Relation) { 207 if (firstRefs instanceof Node) { 208 return "<html>" + trn( 209 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 210 + " It is still referred to by node {1}.<br>" 211 + "Please load the node, remove the reference to the relation, and upload again.", 212 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 213 + " It is still referred to by nodes {1}.<br>" 214 + "Please load the nodes, remove the reference to the relation, and upload again.", 215 conflict.b.size(), objId, refIdsString) + "</html>"; 216 } else if (firstRefs instanceof Way) { 217 return "<html>" + trn( 218 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 219 + " It is still referred to by way {1}.<br>" 220 + "Please load the way, remove the reference to the relation, and upload again.", 221 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 222 + " It is still referred to by ways {1}.<br>" 223 + "Please load the ways, remove the reference to the relation, and upload again.", 224 conflict.b.size(), objId, refIdsString) + "</html>"; 225 } else if (firstRefs instanceof Relation) { 226 return "<html>" + trn( 227 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 228 + " It is still referred to by relation {1}.<br>" 229 + "Please load the relation, remove the reference to the relation, and upload again.", 230 "<strong>Failed</strong> to delete <strong>relation {0}</strong>." 231 + " It is still referred to by relations {1}.<br>" 232 + "Please load the relations, remove the reference to the relation, and upload again.", 233 conflict.b.size(), objId, refIdsString) + "</html>"; 234 } else { 235 throw new IllegalStateException(); 236 } 237 } else { 238 throw new IllegalStateException(); 128 239 } 129 m = Pattern.compile("Precondition failed: Node (\\d+) is still used by ways (\\d+(?:,\\d+)*)\\.").matcher(msg); 130 if (m.matches()) { 131 long childNode = Long.parseLong(m.group(1)); 132 Set<Long> parentWays = new TreeSet<Long>(); // Error message can contain several times the same way 133 for (String s : m.group(2).split(",")) { 134 parentWays.add(Long.parseLong(s)); 135 } 136 return explainDeletedNodeStillInUse(e, childNode, parentWays); 137 } 138 } 139 msg = tr( 140 "<html>Uploading to the server <strong>failed</strong> because your current<br>" 141 + "dataset violates a precondition.<br>" + "The error message is:<br>" + "{0}" + "</html>", 142 escapeReservedCharactersHTML(e.getMessage())); 143 return msg; 240 } else { 241 return tr( 242 "<html>Uploading to the server <strong>failed</strong> because your current<br>" 243 + "dataset violates a precondition.<br>" + "The error message is:<br>" + "{0}" + "</html>", 244 escapeReservedCharactersHTML(e.getMessage())); 245 } 144 246 } 145 247 … … 276 378 if (closeDate == null) { 277 379 msg = tr( 278 "<html>Closing of changeset <strong>{0}</strong> failed <br>because it has already been closed. </html>",380 "<html>Closing of changeset <strong>{0}</strong> failed <br>because it has already been closed.", 279 381 changesetId 280 382 ); … … 283 385 msg = tr( 284 386 "<html>Closing of changeset <strong>{0}</strong> failed<br>" 285 +" because it has already been closed on {1}. </html>",387 +" because it has already been closed on {1}.", 286 388 changesetId, 287 389 dateFormat.format(closeDate) … … 295 397 msg 296 398 ); 297 } 298 msg = tr(299 "<html>The server reported that it has detected a conflict.</html>"300 );399 } else { 400 msg = tr( 401 "<html>The server reported that it has detected a conflict."); 402 } 301 403 return msg; 302 404 } … … 313 415 msg = tr( 314 416 "<html>Failed to upload to changeset <strong>{0}</strong><br>" 315 +"because it has already been closed on {1}. </html>",417 +"because it has already been closed on {1}.", 316 418 e.getChangesetId(), 317 419 e.getClosedOn() == null ? "?" : dateFormat.format(e.getClosedOn()) … … 354 456 String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''<br>" 355 457 + "for security reasons. This is most likely because you are running<br>" 356 + "in an applet and because you did not load your applet from ''{1}''. </html>", apiUrl, host);458 + "in an applet and because you did not load your applet from ''{1}''.", apiUrl, host); 357 459 return message; 358 460 } … … 369 471 String apiUrl = e.getUrl(); 370 472 String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''.<br>" 371 + "Please check your internet connection. </html>", apiUrl);473 + "Please check your internet connection.", apiUrl); 372 474 e.printStackTrace(); 373 475 return message; … … 417 519 String apiUrl = e.getUrl(); 418 520 String message = tr("<html>The OSM server<br>" + "''{0}''<br>" + "reported an internal server error.<br>" 419 + "This is most likely a temporary problem. Please try again later. </html>", apiUrl);521 + "This is most likely a temporary problem. Please try again later.", apiUrl); 420 522 e.printStackTrace(); 421 523 return message; … … 495 597 String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''.<br>" 496 598 + "Host name ''{1}'' could not be resolved. <br>" 497 + "Please check the API URL in your preferences and your internet connection. </html>", apiUrl, host);599 + "Please check the API URL in your preferences and your internet connection.", apiUrl, host); 498 600 e.printStackTrace(); 499 601 return message; -
trunk/src/org/openstreetmap/josm/tools/Utils.java
r4668 r4816 21 21 import java.util.ArrayList; 22 22 import java.util.Collection; 23 import java.util.Iterator; 23 24 import java.util.List; 24 25 … … 396 397 return sorted; 397 398 } 399 400 /** 401 * Represents a function that can be applied to objects of {@code A} and 402 * returns objects of {@code B}. 403 * @param <A> class of input objects 404 * @param <B> class of transformed objects 405 */ 406 public static interface Function<A, B> { 407 408 /** 409 * Applies the function on {@code x}. 410 * @param x an object of 411 * @return the transformed object 412 */ 413 B apply(A x); 414 } 415 416 /** 417 * Transforms the collection {@code c} into an unmodifiable collection and 418 * applies the {@link Function} {@code f} on each element upon access. 419 * @param <A> class of input collection 420 * @param <B> class of transformed collection 421 * @param c a collection 422 * @param f a function that transforms objects of {@code A} to objects of {@code B} 423 * @return the transformed unmodifiable collection 424 */ 425 public static <A, B> Collection<B> transform(final Collection<A> c, final Function<A, B> f) { 426 return new Collection<B>() { 427 428 @Override 429 public int size() { 430 return c.size(); 431 } 432 433 @Override 434 public boolean isEmpty() { 435 return c.isEmpty(); 436 } 437 438 @Override 439 public boolean contains(Object o) { 440 return c.contains(o); 441 } 442 443 @Override 444 public Object[] toArray() { 445 return c.toArray(); 446 } 447 448 @Override 449 public <T> T[] toArray(T[] a) { 450 return c.toArray(a); 451 } 452 453 @Override 454 public String toString() { 455 return c.toString(); 456 } 457 458 @Override 459 public Iterator<B> iterator() { 460 return new Iterator<B>() { 461 462 private Iterator<A> it = c.iterator(); 463 464 @Override 465 public boolean hasNext() { 466 return it.hasNext(); 467 } 468 469 @Override 470 public B next() { 471 return f.apply(it.next()); 472 } 473 474 @Override 475 public void remove() { 476 throw new UnsupportedOperationException(); 477 } 478 }; 479 } 480 481 @Override 482 public boolean add(B e) { 483 throw new UnsupportedOperationException(); 484 } 485 486 @Override 487 public boolean remove(Object o) { 488 throw new UnsupportedOperationException(); 489 } 490 491 @Override 492 public boolean containsAll(Collection<?> c) { 493 throw new UnsupportedOperationException(); 494 } 495 496 @Override 497 public boolean addAll(Collection<? extends B> c) { 498 throw new UnsupportedOperationException(); 499 } 500 501 @Override 502 public boolean removeAll(Collection<?> c) { 503 throw new UnsupportedOperationException(); 504 } 505 506 @Override 507 public boolean retainAll(Collection<?> c) { 508 throw new UnsupportedOperationException(); 509 } 510 511 @Override 512 public void clear() { 513 throw new UnsupportedOperationException(); 514 } 515 }; 516 } 398 517 }
Note:
See TracChangeset
for help on using the changeset viewer.