Changeset 2418 in josm for trunk/src/org/openstreetmap/josm/data/osm
- Timestamp:
- 2009-11-09T08:06:56+01:00 (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeVisitor.java
r2417 r2418 5 5 import java.util.Collection; 6 6 import java.util.HashMap; 7 import java.util.HashSet; 7 8 import java.util.LinkedList; 8 9 import java.util.List; 9 10 import java.util.Map; 11 import java.util.Set; 10 12 import java.util.logging.Logger; 11 13 … … 38 40 * Key is the primitive id in their dataset, the value is the id in my dataset 39 41 */ 40 private Map<Long, Long> merged; 42 private Map<Long, Long> mergedMap; 43 /** a set of primitive ids for which we have to fix references (to nodes and 44 * to relation members) after the first phase of merging 45 */ 46 private Set<Long> fixReferences; 41 47 42 48 /** … … 52 58 this.theirDataSet = theirDataSet; 53 59 conflicts = new ConflictCollection(); 54 merged = new HashMap<Long, Long>(); 60 mergedMap = new HashMap<Long, Long>(); 61 fixReferences = new HashSet<Long>(); 55 62 } 56 63 … … 91 98 } 92 99 if (my.hasEqualSemanticAttributes(other)) { 100 mergedMap.put(other.getUniqueId(), my.getUniqueId()); 93 101 if (my.isDeleted() != other.isDeleted()) { 94 102 // differences in deleted state have to be merged manually 95 103 // 96 104 conflicts.add(my, other); 97 merged.put(other.getUniqueId(), my.getUniqueId());98 105 } else { 99 106 // copy the technical attributes from other … … 103 110 my.setTimestamp(other.getTimestamp()); 104 111 my.setModified(other.isModified()); 105 merged.put(other.getUniqueId(), my.getUniqueId());112 fixReferences.add(other.getUniqueId()); 106 113 } 107 114 return; … … 120 127 my.mergeFrom(other); 121 128 myDataSet.addPrimitive(my); 122 merged.put(other.getUniqueId(), my.getUniqueId()); 129 mergedMap.put(other.getUniqueId(), my.getUniqueId()); 130 fixReferences.add(other.getUniqueId()); 123 131 } 124 132 … … 136 144 137 145 protected OsmPrimitive getMergeTarget(OsmPrimitive mergeSource) { 138 Long targetId = merged .get(mergeSource.getUniqueId());146 Long targetId = mergedMap.get(mergeSource.getUniqueId()); 139 147 if (targetId == null) 140 throw new RuntimeException( "no merge target for merge primitive " + mergeSource.getUniqueId() + " of type " + mergeSource.getType());148 throw new RuntimeException(tr("Missing merge target for way with id {0}", mergeSource.getUniqueId())); 141 149 return myDataSet.getPrimitiveById(targetId, mergeSource.getType()); 142 150 } … … 160 168 public void fixReferences() { 161 169 for (Way w : theirDataSet.getWays()) { 162 if (!conflicts.hasConflictForTheir(w) ) {170 if (!conflicts.hasConflictForTheir(w) && fixReferences.contains(w.getUniqueId())) { 163 171 mergeNodeList(w); 164 172 fixIncomplete(w); … … 166 174 } 167 175 for (Relation r : theirDataSet.getRelations()) { 168 if (!conflicts.hasConflictForTheir(r) ) {176 if (!conflicts.hasConflictForTheir(r) && fixReferences.contains(r.getUniqueId())) { 169 177 mergeRelationMembers(r); 170 178 } … … 262 270 // merge other into an existing primitive with the same id, if possible 263 271 // 264 if (my != null) { 265 if (my.getVersion() <= other.getVersion()) { 266 if (! my.isVisible() && other.isVisible()) { 267 // should not happen 268 // 269 logger.warning(tr("My primitive with id {0} and version {1} is visible although " 270 + "their primitive with lower version {2} is not visible. " 271 + "Can't deal with this inconsistency. Keeping my primitive. ", 272 Long.toString(my.getId()),Long.toString(my.getVersion()), Long.toString(other.getVersion()) 273 )); 274 merged.put(other.getUniqueId(), my.getUniqueId()); 275 } else if (my.isVisible() && ! other.isVisible()) { 276 // this is always a conflict because the user has to decide whether 277 // he wants to create a clone of its local primitive or whether he 278 // wants to purge my from the local dataset. He can't keep it unchanged 279 // because it was deleted on the server. 280 // 281 conflicts.add(my,other); 282 merged.put(other.getUniqueId(), my.getUniqueId()); 283 } else if (my.incomplete && !other.incomplete) { 284 // my is incomplete, other completes it 285 // => merge other onto my 286 // 287 my.mergeFrom(other); 288 merged.put(other.getUniqueId(), my.getUniqueId()); 289 } else if (!my.incomplete && other.incomplete) { 290 // my is complete and the other is incomplete 291 // => keep mine, we have more information already 292 // 293 merged.put(other.getUniqueId(), my.getUniqueId()); 294 } else if (my.incomplete && other.incomplete) { 295 // my and other are incomplete. Doesn't matter which one to 296 // take. We take mine. 297 // 298 merged.put(other.getUniqueId(), my.getUniqueId()); 299 } else if (my.isDeleted() && ! other.isDeleted() && my.getVersion() == other.getVersion()) { 300 // same version, but my is deleted. Assume mine takes precedence 301 // otherwise too many conflicts when refreshing from the server 302 merged.put(other.getUniqueId(), my.getUniqueId()); 303 } else if (my.isDeleted() != other.isDeleted()) { 304 // differences in deleted state have to be resolved manually 305 // 306 conflicts.add(my,other); 307 merged.put(other.getUniqueId(), my.getUniqueId()); 308 } else if (! my.isModified() && other.isModified()) { 309 // my not modified. We can assume that other is the most recent version. 310 // clone it onto my. But check first, whether other is deleted. if so, 311 // make sure that my is not references anymore in myDataSet. 312 // 313 if (other.isDeleted()) { 314 myDataSet.unlinkReferencesToPrimitive(my); 315 } 316 my.mergeFrom(other); 317 merged.put(other.getUniqueId(), my.getUniqueId()); 318 } else if (! my.isModified() && !other.isModified() && my.getVersion() == other.getVersion()) { 319 // both not modified. Keep mine 320 // 321 merged.put(other.getUniqueId(),my.getUniqueId()); 322 } else if (! my.isModified() && !other.isModified() && my.getVersion() < other.getVersion()) { 323 // my not modified but other is newer. clone other onto mine. 324 // 325 my.mergeFrom(other); 326 merged.put(other.getUniqueId(),my.getUniqueId()); 327 } else if (my.isModified() && ! other.isModified() && my.getVersion() == other.getVersion()) { 328 // my is same as other but mine is modified 329 // => keep mine 330 merged.put(other.getUniqueId(), my.getUniqueId()); 331 } else if (! my.hasEqualSemanticAttributes(other)) { 332 // my is modified and is not semantically equal with other. Can't automatically 333 // resolve the differences 334 // => create a conflict 335 conflicts.add(my,other); 336 merged.put(other.getUniqueId(), my.getUniqueId()); 337 } else { 338 // clone from other, but keep the modified flag. Clone will mainly copy 339 // technical attributes like timestamp or user information. Semantic 340 // attributes should already be equal if we get here. 341 // 342 my.mergeFrom(other); 343 my.setModified(true); 344 merged.put(other.getUniqueId(), my.getUniqueId()); 345 } 346 } else { 347 // my.version > other.version => keep my version 348 merged.put(other.getUniqueId(), my.getUniqueId()); 349 } 272 if (my == null) 273 return false; 274 mergedMap.put(other.getUniqueId(), my.getUniqueId()); 275 if (my.getVersion() > other.getVersion()) 276 // my.version > other.version => keep my version 350 277 return true; 351 } 352 return false; 353 } 354 278 if (! my.isVisible() && other.isVisible()) { 279 // should not happen 280 // 281 logger.warning(tr("My primitive with id {0} and version {1} is visible although " 282 + "their primitive with lower version {2} is not visible. " 283 + "Can't deal with this inconsistency. Keeping my primitive. ", 284 Long.toString(my.getId()),Long.toString(my.getVersion()), Long.toString(other.getVersion()) 285 )); 286 } else if (my.isVisible() && ! other.isVisible()) { 287 // this is always a conflict because the user has to decide whether 288 // he wants to create a clone of its local primitive or whether he 289 // wants to purge my from the local dataset. He can't keep it unchanged 290 // because it was deleted on the server. 291 // 292 conflicts.add(my,other); 293 } else if (my.incomplete && !other.incomplete) { 294 // my is incomplete, other completes it 295 // => merge other onto my 296 // 297 my.mergeFrom(other); 298 fixReferences.add(other.getUniqueId()); 299 } else if (!my.incomplete && other.incomplete) { 300 // my is complete and the other is incomplete 301 // => keep mine, we have more information already 302 // 303 } else if (my.incomplete && other.incomplete) { 304 // my and other are incomplete. Doesn't matter which one to 305 // take. We take mine. 306 // 307 } else if (my.isDeleted() && ! other.isDeleted() && my.getVersion() == other.getVersion()) { 308 // same version, but my is deleted. Assume mine takes precedence 309 // otherwise too many conflicts when refreshing from the server 310 } else if (my.isDeleted() != other.isDeleted()) { 311 // differences in deleted state have to be resolved manually 312 // 313 conflicts.add(my,other); 314 } else if (! my.isModified() && other.isModified()) { 315 // my not modified. We can assume that other is the most recent version. 316 // clone it onto my. But check first, whether other is deleted. if so, 317 // make sure that my is not references anymore in myDataSet. 318 // 319 if (other.isDeleted()) { 320 myDataSet.unlinkReferencesToPrimitive(my); 321 } 322 my.mergeFrom(other); 323 fixReferences.add(other.getUniqueId()); 324 } else if (! my.isModified() && !other.isModified() && my.getVersion() == other.getVersion()) { 325 // both not modified. Keep mine 326 // 327 } else if (! my.isModified() && !other.isModified() && my.getVersion() < other.getVersion()) { 328 // my not modified but other is newer. clone other onto mine. 329 // 330 my.mergeFrom(other); 331 fixReferences.add(other.getUniqueId()); 332 } else if (my.isModified() && ! other.isModified() && my.getVersion() == other.getVersion()) { 333 // my is same as other but mine is modified 334 // => keep mine 335 } else if (! my.hasEqualSemanticAttributes(other)) { 336 // my is modified and is not semantically equal with other. Can't automatically 337 // resolve the differences 338 // => create a conflict 339 conflicts.add(my,other); 340 } else { 341 // clone from other, but keep the modified flag. mergeFrom will mainly copy 342 // technical attributes like timestamp or user information. Semantic 343 // attributes should already be equal if we get here. 344 // 345 my.mergeFrom(other); 346 my.setModified(true); 347 fixReferences.add(other.getUniqueId()); 348 } 349 return true; 350 } 355 351 356 352 /**
Note:
See TracChangeset
for help on using the changeset viewer.