source: josm/trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetMergerTest.java@ 6881

Last change on this file since 6881 was 6881, checked in by Don-vip, 10 years ago

javadoc/code style/minor refactorization

File size: 29.6 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm;
3
4import static org.junit.Assert.assertEquals;
5import static org.junit.Assert.assertFalse;
6import static org.junit.Assert.assertNotNull;
7import static org.junit.Assert.assertTrue;
8
9import java.io.StringWriter;
10import java.util.Arrays;
11import java.util.Calendar;
12import java.util.Date;
13import java.util.GregorianCalendar;
14
15import org.junit.After;
16import org.junit.Before;
17import org.junit.BeforeClass;
18import org.junit.Test;
19import org.openstreetmap.josm.Main;
20import org.openstreetmap.josm.data.coor.LatLon;
21import org.openstreetmap.josm.data.projection.Projections;
22
23public class DataSetMergerTest {
24
25 @BeforeClass
26 public static void init() {
27 Main.initApplicationPreferences();
28 }
29
30 private DataSet my;
31 private DataSet their;
32
33 /**
34 * Setup test.
35 */
36 @Before
37 public void setUp() {
38 User.clearUserMap();
39 my = new DataSet();
40 my.setVersion("0.6");
41 their = new DataSet();
42 their.setVersion("0.6");
43 Main.setProjection(Projections.getProjectionByCode("EPSG:3857")); // Mercator
44 }
45
46 private void runConsistencyTests(DataSet ds) throws Exception {
47 StringWriter writer = new StringWriter();
48 DatasetConsistencyTest test = new DatasetConsistencyTest(ds, writer);
49 test.checkReferrers();
50 test.checkCompleteWaysWithIncompleteNodes();
51 test.searchNodes();
52 test.searchWays();
53 test.referredPrimitiveNotInDataset();
54 test.checkZeroNodesWays();
55 String result = writer.toString();
56 if (result.length() > 0)
57 throw new RuntimeException(result);
58 }
59
60 @After
61 public void checkDatasets() throws Exception {
62 runConsistencyTests(my);
63 runConsistencyTests(their);
64 }
65
66 /**
67 * two identical nodes, even in id and version. No confict expected.
68 *
69 * Can happen if data is loaded in two layers and then merged from one layer
70 * on the other.
71 */
72 @Test
73 public void nodeSimple_IdenticalNoConflict() {
74 Node n = new Node(new LatLon(0,0));
75 n.setOsmId(1,1);
76 n.setModified(false);
77 n.put("key1", "value1");
78 my.addPrimitive(n);
79
80 Node n1 = new Node(new LatLon(0,0));
81 n1.setOsmId(1,1);
82 n1.setModified(false);
83 n1.put("key1", "value1");
84 their.addPrimitive(n1);
85
86
87 DataSetMerger visitor = new DataSetMerger(my,their);
88 visitor.merge();
89
90 Node n2 = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
91 assertTrue(visitor.getConflicts().isEmpty());
92 assertTrue(n1 != n2); // make sure we have a clone
93 assertEquals(1, n2.getId());
94 assertEquals(1, n2.getVersion());
95 assertEquals(false, n2.isModified());
96 assertEquals("value1", n2.get("key1"));
97
98 // merge target not modified after merging
99 assertTrue(!n2.isModified());
100 }
101
102 /**
103 * two nodes, my is unmodified, their is updated and has a higher version
104 * => their version is going to be the merged version
105 *
106 */
107 @Test
108 public void nodeSimple_locallyUnmodifiedNoConflict() {
109 Node n = new Node(new LatLon(0,0));
110 n.setOsmId(1,1);
111 n.setModified(false);
112 n.put("key1", "value1");
113 my.addPrimitive(n);
114
115 Node n1 = new Node(new LatLon(0,0));
116 n1.setOsmId(1,2);
117 n1.setModified(false);
118 n1.put("key1", "value1-new");
119 n1.put("key2", "value2");
120 their.addPrimitive(n1);
121
122
123 DataSetMerger visitor = new DataSetMerger(my,their);
124 visitor.merge();
125
126 Node n2 = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
127 assertTrue(visitor.getConflicts().isEmpty());
128 assertTrue(n == n2); // make sure the merged node is still the original node
129 assertTrue(n2.getDataSet() == my);
130 assertEquals(1, n2.getId());
131 assertEquals(2, n2.getVersion());
132 assertEquals(false, n2.isModified());
133 assertEquals("value1-new", n2.get("key1"));
134 assertEquals("value2", n2.get("key2"));
135
136 // the merge target should not be modified
137 assertTrue(!n2.isModified());
138 }
139
140 /**
141 * Node with same id, my is modified, their has a higher version
142 * => results in a conflict
143 *
144 * Use case: node which is modified locally and updated by another mapper on
145 * the server
146 */
147 @Test
148 public void nodeSimple_TagConflict() {
149 Node n = new Node(new LatLon(0,0));
150 n.setOsmId(1,1);
151 n.setModified(true);
152 n.put("key1", "value1");
153 n.put("key2", "value2");
154 my.addPrimitive(n);
155
156 Node n1 = new Node(new LatLon(0,0));
157 n1.setOsmId(1,2);
158 n1.setModified(false);
159 n1.put("key1", "value1-new");
160
161 their.addPrimitive(n1);
162
163
164 DataSetMerger visitor = new DataSetMerger(my,their);
165 visitor.merge();
166
167 Node n2 = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
168 assertEquals(1,visitor.getConflicts().size());
169 assertTrue(n == n2);
170 assertTrue(n1 != n2);
171 assertTrue(n1.getDataSet() == their);
172 }
173
174 /**
175 * node with same id, my is deleted, their has a higher version
176 * => results in a conflict
177 *
178 * Use case: node which is deleted locally and updated by another mapper on
179 * the server
180 */
181 @Test
182 public void nodeSimple_DeleteConflict() {
183 Node n = new Node(1, 1);
184 n.setCoor(new LatLon(0,0));
185 n.setDeleted(true);
186 n.put("key1", "value1");
187 my.addPrimitive(n);
188
189 Node n1 = new Node(new LatLon(0,0));
190 n1.setOsmId(1,2);
191 n1.setModified(false);
192 n1.put("key1", "value1-new");
193 n1.put("key2", "value2");
194 their.addPrimitive(n1);
195
196
197 DataSetMerger visitor = new DataSetMerger(my,their);
198 visitor.merge();
199
200 Node n2 = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
201 assertEquals(1,visitor.getConflicts().size());
202 assertTrue(n == n2);
203 assertTrue(n1 != n2);
204 assertTrue(n1.getDataSet() == their);
205 }
206
207 /**
208 * My node is deleted, their node has the same id and version and is not deleted.
209 * => mine has precedence
210 *
211 */
212 @Test
213 public void nodeSimple_DeleteConflict_2() {
214 Node n = new Node(new LatLon(0,0));
215 n.setOsmId(1,1);
216 n.setDeleted(true);
217 my.addPrimitive(n);
218
219 Node n1 = new Node(new LatLon(0,0));
220 n1.setOsmId(1,1);
221 their.addPrimitive(n1);
222
223
224 DataSetMerger visitor = new DataSetMerger(my,their);
225 visitor.merge();
226
227 Node n2 = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
228 assertEquals(0,visitor.getConflicts().size());
229 assertEquals(true, n2.isVisible());
230 assertTrue(n == n2);
231 assertTrue(n.getDataSet() == my);
232 assertTrue(n1.getDataSet() == their);
233 }
234
235 /**
236 * My and their node are new but semantically equal. My node is deleted.
237 *
238 * => Ignore my node, no conflict
239 */
240 @Test
241 public void nodeSimple_DeleteConflict_3() {
242 Node n = new Node(new LatLon(1,1));
243 n.setDeleted(true);
244 my.addPrimitive(n);
245
246 Node n1 = new Node(new LatLon(1,1));
247 their.addPrimitive(n1);
248
249
250 DataSetMerger visitor = new DataSetMerger(my,their);
251 visitor.merge();
252
253 assertEquals(0, visitor.getConflicts().size());
254 assertTrue(n.getDataSet() == my);
255 assertTrue(n1.getDataSet() == their);
256 }
257
258 /**
259 * My and their node are new but semantically equal. Both are deleted.
260 *
261 * => take mine
262 *
263 */
264 @Test
265 public void nodeSimple_DeleteConflict_4() {
266 Node n = new Node(new LatLon(1,1));
267 n.setDeleted(true);
268 my.addPrimitive(n);
269
270 Node n1 = new Node(new LatLon(1,1));
271 n1.setDeleted(true);
272 their.addPrimitive(n1);
273
274
275 DataSetMerger visitor = new DataSetMerger(my,their);
276 visitor.merge();
277
278 assertEquals(0,visitor.getConflicts().size());
279 Node n2 = (Node)my.getNodes().toArray()[0];
280 assertTrue(n2 == n);
281 assertTrue(n2.isDeleted());
282 }
283
284 /**
285 * their node has no assigned id (id == 0) and is semantically equal to one of my
286 * nodes with id == 0
287 *
288 * => merge it onto my node.
289 *
290 */
291 @Test
292 public void nodeSimple_NoIdSemanticallyEqual() {
293
294 Calendar cal = GregorianCalendar.getInstance();
295 User myUser = User.createOsmUser(1111, "my");
296
297 User theirUser = User.createOsmUser(222, "their");
298
299 Node n = new Node();
300 n.setCoor(new LatLon(0,0));
301 n.put("key1", "value1");
302 n.setUser(myUser);
303 n.setTimestamp(cal.getTime());
304
305 my.addPrimitive(n);
306
307 Node n1 = new Node();
308 n1.setCoor(new LatLon(0,0));
309 n1.put("key1", "value1");
310 cal.add(Calendar.HOUR, 1);
311 Date timestamp = cal.getTime();
312 n1.setTimestamp(timestamp);
313 n1.setUser(theirUser);
314 their.addPrimitive(n1);
315
316
317 DataSetMerger visitor = new DataSetMerger(my,their);
318 visitor.merge();
319
320 Node n2 = my.getNodes().iterator().next();
321 assertEquals(0,visitor.getConflicts().size());
322 assertEquals("value1",n2.get("key1"));
323 assertEquals(true, n1.getTimestamp().equals(n2.getTimestamp()));
324 assertEquals(theirUser,n2.getUser());
325 assertTrue(n2 == n);
326 assertTrue(n2 != n1);
327 assertTrue(n2.getDataSet() == my);
328 }
329
330 /**
331 * my node is incomplete, their node is complete
332 *
333 * => merge it onto my node. My node becomes complete
334 *
335 */
336 @Test
337 public void nodeSimple_IncompleteNode() {
338
339 Node n = new Node(1);
340 my.addPrimitive(n);
341
342 Node n1 = new Node();
343 n1.setCoor(new LatLon(0,0));
344 n1.setOsmId(1,1);
345 n1.put("key1", "value1");
346 Date timestamp = new Date();
347 n1.setTimestamp(timestamp);
348 their.addPrimitive(n1);
349
350
351 DataSetMerger visitor = new DataSetMerger(my,their);
352 visitor.merge();
353
354 Node n2 = my.getNodes().iterator().next();
355 assertEquals(0,visitor.getConflicts().size());
356 assertEquals("value1",n2.get("key1"));
357 assertEquals(true, n1.getTimestamp().equals(n2.getTimestamp()));
358 assertEquals(false, n2.isIncomplete());
359 assertTrue(n2 == n);
360 }
361
362 /**
363 * their way has a higher version and different tags. the nodes are the same. My
364 * way is not modified. Merge is possible. No conflict.
365 *
366 * => merge it onto my way.
367 *
368 */
369 @Test
370 public void waySimple_IdenicalNodesDifferentTags() {
371
372 // -- the target dataset
373
374 Node n1 = new Node();
375 n1.setCoor(new LatLon(0,0));
376 n1.setOsmId(1,1);
377 my.addPrimitive(n1);
378
379 Node n2 = new Node();
380 n2.setCoor(new LatLon(0,0));
381 n2.setOsmId(2,1);
382
383 my.addPrimitive(n2);
384
385 Way myWay = new Way();
386 myWay.setOsmId(3,1);
387 myWay.put("key1", "value1");
388 myWay.addNode(n1);
389 myWay.addNode(n2);
390 my.addPrimitive(myWay);
391
392 // -- the source data set
393
394 Node n3 = new Node(new LatLon(0,0));
395 n3.setOsmId(1,1);
396 their.addPrimitive(n3);
397
398 Node n4 = new Node(new LatLon(1,1));
399 n4.setOsmId(2,1);
400 their.addPrimitive(n4);
401
402 Way theirWay = new Way();
403 theirWay.setOsmId(3,2);
404 theirWay.put("key1", "value1");
405 theirWay.put("key2", "value2");
406 theirWay.addNode(n3);
407 theirWay.addNode(n4);
408 their.addPrimitive(theirWay);
409
410
411 DataSetMerger visitor = new DataSetMerger(my,their);
412 visitor.merge();
413
414 // -- tests
415 Way merged = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
416 assertEquals(0,visitor.getConflicts().size());
417 assertEquals("value1",merged.get("key1"));
418 assertEquals("value2",merged.get("key2"));
419 assertEquals(3,merged.getId());
420 assertEquals(2,merged.getVersion());
421 assertEquals(2,merged.getNodesCount());
422 assertEquals(1,merged.getNode(0).getId());
423 assertEquals(2,merged.getNode(1).getId());
424 assertTrue(merged == myWay);
425 assertTrue(merged.getDataSet() == my);
426
427 Node mergedNode = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
428 assertTrue(mergedNode == n1);
429 mergedNode = (Node)my.getPrimitiveById(2, OsmPrimitiveType.NODE);
430 assertTrue(mergedNode == n2);
431
432 assertTrue(!merged.isModified());
433 }
434
435 /**
436 * their way has a higher version and different tags. And it has more nodes. Two
437 * of the existing nodes are modified.
438 *
439 * => merge it onto my way, no conflict
440 *
441 */
442 @Test
443 public void waySimple_AdditionalNodesAndChangedNodes() {
444
445 // -- my data set
446
447 Node n1 = new Node(new LatLon(0,0));
448 n1.setOsmId(1,1);
449 my.addPrimitive(n1);
450
451 Node n2 = new Node(new LatLon(1,1));
452 n2.setOsmId(2,1);
453 my.addPrimitive(n2);
454
455 Way myWay = new Way();
456 myWay.setOsmId(3,1);
457 myWay.addNode(n1);
458 myWay.addNode(n2);
459 my.addPrimitive(myWay);
460
461 // --- their data set
462
463 Node n3 = new Node(new LatLon(0,0));
464 n3.setOsmId(1,1);
465 their.addPrimitive(n3);
466
467 Node n5 = new Node(new LatLon(1,1));
468 n5.setOsmId(4,1);
469
470 their.addPrimitive(n5);
471
472 Node n4 = new Node(new LatLon(2,2));
473 n4.setOsmId(2,2);
474 n4.put("key1", "value1");
475 their.addPrimitive(n4);
476
477
478 Way theirWay = new Way();
479 theirWay.setOsmId(3,2);
480 theirWay.addNode(n3);
481 theirWay.addNode(n5); // insert a node
482 theirWay.addNode(n4); // this one is updated
483 their.addPrimitive(theirWay);
484
485 DataSetMerger visitor = new DataSetMerger(my,their);
486 visitor.merge();
487
488 // -- tests
489 Way merged = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
490 assertEquals(0,visitor.getConflicts().size());
491 assertEquals(3,merged.getId());
492 assertEquals(2,merged.getVersion());
493 assertEquals(3,merged.getNodesCount());
494 assertEquals(1,merged.getNode(0).getId());
495 assertEquals(4,merged.getNode(1).getId());
496 assertEquals(2,merged.getNode(2).getId());
497 assertEquals("value1",merged.getNode(2).get("key1"));
498
499 assertTrue(merged.getNode(0) == n1);
500 assertTrue(merged.getNode(1) != n5); // must be clone of the original node in their
501 assertTrue(merged.getNode(2) == n2);
502
503 assertTrue(!merged.isModified()); // the target wasn't modified before merging, it
504 // mustn't be after merging
505 }
506
507 /**
508 * their way has a higher version and different nodes. My way is modified.
509 *
510 * => merge onto my way not possible, create a conflict
511 *
512 */
513 @Test
514 public void waySimple_DifferentNodesAndMyIsModified() {
515
516 // -- the target dataset
517
518 Node n1 = new Node(new LatLon(0,0));
519 n1.setOsmId(1,1);
520 my.addPrimitive(n1);
521
522 Node n2 = new Node(new LatLon(1,1));
523 n2.setOsmId(2,1);
524 my.addPrimitive(n2);
525
526 Way myWay = new Way();
527 myWay.setOsmId(3,1);
528
529 myWay.addNode(n1);
530 myWay.addNode(n2);
531 myWay.setModified(true);
532 myWay.put("key1", "value1");
533 my.addPrimitive(myWay);
534
535 // -- the source dataset
536
537 Node n3 = new Node(new LatLon(0,0));
538 n3.setOsmId(1,1);
539 their.addPrimitive(n3);
540
541 Node n5 = new Node(new LatLon(1,1));
542 n5.setOsmId(4,1);
543 their.addPrimitive(n5);
544
545 Node n4 = new Node(new LatLon(2,2));
546 n4.setOsmId(2,1);
547 n4.put("key1", "value1");
548 their.addPrimitive(n4);
549
550
551 Way theirWay = new Way();
552 theirWay.setOsmId(3,2);
553
554 theirWay.addNode(n3);
555 theirWay.addNode(n5); // insert a node
556 theirWay.addNode(n4); // this one is updated
557 their.addPrimitive(theirWay);
558
559
560 DataSetMerger visitor = new DataSetMerger(my, their);
561 visitor.merge();
562
563 Way merged = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
564 assertEquals(1,visitor.getConflicts().size());
565 assertEquals(3,merged.getId());
566 assertEquals(1,merged.getVersion());
567 assertEquals(2,merged.getNodesCount());
568 assertEquals(1,merged.getNode(0).getId());
569 assertEquals(2,merged.getNode(1).getId());
570 assertEquals("value1",merged.get("key1"));
571 }
572
573
574 /**
575 * their way is not visible anymore.
576 *
577 * => conflict
578 *
579 */
580 @Test
581 public void waySimple_TheirVersionNotVisibleMyIsModified() {
582
583
584 Node mn1 = new Node(new LatLon(0,0));
585 mn1.setOsmId(1,1);
586 my.addPrimitive(mn1);
587
588 Node mn2 = new Node(new LatLon(1,1));
589 mn2.setOsmId(2,1);
590 my.addPrimitive(mn2);
591
592 Way myWay = new Way();
593 myWay.setOsmId(3,1);
594 myWay.addNode(mn1);
595 myWay.addNode(mn2);
596 myWay.setModified(true);
597 my.addPrimitive(myWay);
598
599
600 Way theirWay = new Way();
601 theirWay.setOsmId(3,2);
602 theirWay.setVisible(false);
603 /* Invisible objects fetched from the server should be marked as "deleted".
604 * Otherwise it's an error.
605 */
606 theirWay.setDeleted(true);
607 their.addPrimitive(theirWay);
608
609 DataSetMerger visitor = new DataSetMerger(my,their);
610 visitor.merge();
611
612 Way merged = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
613 assertEquals(1,visitor.getConflicts().size());
614 assertEquals(true, visitor.getConflicts().hasConflictForMy(myWay));
615 assertEquals(true, visitor.getConflicts().hasConflictForTheir(theirWay));
616 assertEquals(myWay,merged);
617 }
618
619 /**
620 * my and their way have no ids, nodes they refer to have an id. but
621 * my and their way are semantically equal. so technical attributes of
622 * their way can be merged on my way. No conflict.
623 *
624 */
625 @Test
626 public void waySimple_twoWaysWithNoId_NodesWithId() {
627
628 // -- my data set
629
630 Node n1 = new Node(new LatLon(0,0));
631 n1.setOsmId(1,1);
632 my.addPrimitive(n1);
633
634 Node n2 = new Node(new LatLon(1,1));
635 n2.setOsmId(2,1);
636 my.addPrimitive(n2);
637
638 Way myWay = new Way();
639 myWay.addNode(n1);
640 myWay.addNode(n2);
641 my.addPrimitive(myWay);
642
643 // -- their data set
644
645 Node n3 = new Node(new LatLon(0,0));
646 n3.setOsmId(1,1);
647 their.addPrimitive(n3);
648
649 Node n4 = new Node(new LatLon(1,1));
650 n4.setOsmId(2,1);
651 their.addPrimitive(n4);
652
653 Way theirWay = new Way();
654 theirWay.addNode(n3);
655 theirWay.addNode(n4);
656 User user = User.createOsmUser(1111, "their");
657 theirWay.setUser(user);
658 theirWay.setTimestamp(new Date());
659 their.addPrimitive(theirWay);
660
661 DataSetMerger visitor = new DataSetMerger(my,their);
662 visitor.merge();
663
664 // -- tests
665 Way merged = (Way)my.getWays().toArray()[0];
666 assertEquals(0,visitor.getConflicts().size());
667 assertEquals("their", merged.getUser().getName());
668 assertEquals(1111, merged.getUser().getId());
669 assertEquals(theirWay.getTimestamp(), merged.getTimestamp());
670 assertTrue(merged == myWay);
671 assertTrue(merged.getNode(0) == n1);
672 assertTrue(merged.getNode(1) == n2);
673
674 assertTrue(!merged.isModified());
675 }
676
677 /**
678 * my and their way have no ids, neither do the nodes they refer to. but
679 * my and their way are semantically equal. so technical attributes of
680 * their way can be merged on my way. No conflict.
681 *
682 */
683 @Test
684 public void waySimple_twoWaysWithNoId_NodesWithoutId() {
685
686 // -- my data set
687
688 Node n1 = new Node(new LatLon(0,0));
689 my.addPrimitive(n1);
690
691 Node n2 = new Node(new LatLon(1,1));
692 my.addPrimitive(n2);
693
694 Way myWay = new Way();
695 myWay.addNode(n1);
696 myWay.addNode(n2);
697 my.addPrimitive(myWay);
698
699 // -- their data set
700
701 Node n3 = new Node(new LatLon(0,0));
702 their.addPrimitive(n3);
703
704 Node n4 = new Node(new LatLon(1,1));
705 their.addPrimitive(n4);
706
707 Way theirWay = new Way();
708 theirWay.addNode(n3);
709 theirWay.addNode(n4);
710 User user = User.createOsmUser(1111, "their");
711 theirWay.setUser(user);
712 theirWay.setTimestamp(new Date());
713 their.addPrimitive(theirWay);
714
715 DataSetMerger visitor = new DataSetMerger(my,their);
716 visitor.merge();
717
718 // -- tests
719 Way merged = (Way)my.getWays().toArray()[0];
720 assertEquals(0,visitor.getConflicts().size());
721 assertEquals("their", merged.getUser().getName());
722 assertEquals(1111, merged.getUser().getId());
723 assertEquals(theirWay.getTimestamp(), merged.getTimestamp());
724 assertTrue(merged == myWay);
725 assertTrue(merged.getNode(0) == n1);
726 assertTrue(merged.getNode(1) == n2);
727
728 assertTrue(!merged.isModified());
729 }
730
731
732 /**
733 * My dataset includes a deleted node.
734 * Their dataset includes a way with three nodes, the first one being my node.
735 *
736 * => the merged way should include all three nodes. Deleted node should have deleted=false and
737 * special conflict with isDeleted should exist
738 *
739 */
740 @Test
741 public void wayComplex_mergingADeletedNode() {
742
743 // -- my dataset
744
745 Node mn1 = new Node(new LatLon(0,0));
746 mn1.setOsmId(1,1);
747 mn1.setDeleted(true);
748 my.addPrimitive(mn1);
749
750
751 Node tn1 = new Node(new LatLon(0,0));
752 tn1.setOsmId(1,1);
753 their.addPrimitive(tn1);
754
755 Node tn2 = new Node(new LatLon(1,1));
756 tn2.setOsmId(2,1);
757 their.addPrimitive(tn2);
758
759 Node tn3 = new Node(new LatLon(2,2));
760 tn3.setOsmId(3,1);
761 their.addPrimitive(tn3);
762
763 // -- their data set
764 Way theirWay = new Way();
765 theirWay.setOsmId(4,1);
766 theirWay.addNode(tn1);
767 theirWay.addNode(tn2);
768 theirWay.addNode(tn3);
769 theirWay.setUser(User.createOsmUser(1111, "their"));
770 theirWay.setTimestamp(new Date());
771 their.addPrimitive(theirWay);
772
773 DataSetMerger visitor = new DataSetMerger(my,their);
774 visitor.merge();
775
776 assertEquals(1, visitor.getConflicts().size());
777 assertTrue(visitor.getConflicts().get(0).isMyDeleted());
778
779 Way myWay = (Way)my.getPrimitiveById(4, OsmPrimitiveType.WAY);
780 assertEquals(3, myWay.getNodesCount());
781
782 Node n = (Node)my.getPrimitiveById(1,OsmPrimitiveType.NODE);
783 assertTrue(myWay.getNodes().contains(n));
784
785 assertFalse(myWay.isModified());
786 }
787
788 /**
789 * My dataset includes a deleted node.
790 * Their dataset includes a relation with three nodes, the first one being my node.
791 *
792 * => the merged relation should include all three nodes. There should be conflict for deleted
793 * node with isMyDeleted set
794 *
795 */
796 @Test
797 public void relationComplex_mergingADeletedNode() {
798
799
800 Node mn1 = new Node(new LatLon(0,0));
801 mn1.setOsmId(1,1);
802 mn1.setDeleted(true);
803 my.addPrimitive(mn1);
804
805
806 Node tn1 = new Node(new LatLon(0,0));
807 tn1.setOsmId(1,1);
808 their.addPrimitive(tn1);
809
810 Node tn2 = new Node(new LatLon(1,1));
811 tn2.setOsmId(2,1);
812 their.addPrimitive(tn2);
813
814 Node tn3 = new Node(new LatLon(2,2));
815 tn3.setOsmId(3,1);
816 their.addPrimitive(tn3);
817
818
819 Relation theirRelation = new Relation();
820 theirRelation.setOsmId(4,1);
821
822 theirRelation.addMember(new RelationMember("", tn1));
823 theirRelation.addMember(new RelationMember("", tn2));
824 theirRelation.addMember(new RelationMember("", tn3));
825 their.addPrimitive(theirRelation);
826
827 DataSetMerger visitor = new DataSetMerger(my,their);
828 visitor.merge();
829
830 Node n = (Node)my.getPrimitiveById(1,OsmPrimitiveType.NODE);
831 assertTrue(n != null);
832
833 assertEquals(1, visitor.getConflicts().size());
834 assertTrue(visitor.getConflicts().hasConflictForMy(n));
835 assertTrue(visitor.getConflicts().get(0).isMyDeleted());
836
837 Relation r = (Relation)my.getPrimitiveById(4,OsmPrimitiveType.RELATION);
838 assertEquals(3, r.getMembersCount());
839
840 assertFalse(r.isModified());
841 }
842
843 /**
844 * Merge an incomplete way with two incomplete nodes into an empty dataset.
845 *
846 * Use case: a way loaded with a multiget, i.e. GET /api/0.6/ways?ids=123456
847 */
848 @Test
849 public void newIncompleteWay() {
850
851 Node n1 = new Node(1);
852 their.addPrimitive(n1);
853
854 Node n2 = new Node(2);
855 their.addPrimitive(n2);
856
857 Way w3 = new Way(3);
858 w3.setNodes(Arrays.asList(n1,n2));
859 their.addPrimitive(w3);
860 assertTrue(w3.isIncomplete());
861
862
863 DataSetMerger visitor = new DataSetMerger(my, their);
864 visitor.merge();
865
866 assertEquals(0,visitor.getConflicts().size());
867
868 OsmPrimitive p= my.getPrimitiveById(1, OsmPrimitiveType.NODE);
869 assertNotNull(p);
870 assertTrue(p.isIncomplete());
871 p= my.getPrimitiveById(2, OsmPrimitiveType.NODE);
872 assertNotNull(p);
873 assertTrue(p.isIncomplete());
874 p= my.getPrimitiveById(3, OsmPrimitiveType.WAY);
875 assertNotNull(p);
876 assertTrue(p.isIncomplete());
877
878 Way w = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
879 assertNotNull(w);
880 assertTrue(p.isIncomplete());
881 assertEquals(2, w.getNodesCount());
882 assertTrue(w.getNode(0).isIncomplete());
883 assertTrue(w.getNode(1).isIncomplete());
884 }
885
886 /**
887 * Merge an incomplete way with two incomplete nodes into a dataset where the way already exists as complete way.
888 *
889 * Use case: a way loaded with a multiget, i.e. GET /api/0.6/ways?ids=123456 after a "Update selection " of this way
890 */
891 @Test
892 public void incompleteWayOntoCompleteWay() {
893
894 // an incomplete node
895 Node n1 = new Node(1);
896 their.addPrimitive(n1);
897
898 // another incomplete node
899 Node n2 = new Node(2);
900 their.addPrimitive(n2);
901
902 // an incomplete way with two incomplete nodes
903 Way w3 = new Way(3);
904 w3.setNodes(Arrays.asList(n1,n2));
905 their.addPrimitive(w3);
906
907
908 Node n4 = new Node(new LatLon(0,0));
909 n4.setOsmId(1,1);
910 my.addPrimitive(n4);
911
912 Node n5 = new Node(new LatLon(1,1));
913 n5.setOsmId(2,1);
914 my.addPrimitive(n5);
915
916 Way w6 = new Way(3, 1);
917 w6.setNodes(Arrays.asList(n4,n5));
918 my.addPrimitive(w6);
919
920 DataSetMerger visitor = new DataSetMerger(my,their);
921 visitor.merge();
922
923 assertEquals(0,visitor.getConflicts().size());
924
925 OsmPrimitive p= my.getPrimitiveById(1, OsmPrimitiveType.NODE);
926 assertNotNull(p);
927 assertTrue(!p.isIncomplete());
928 p= my.getPrimitiveById(2, OsmPrimitiveType.NODE);
929 assertNotNull(p);
930 assertTrue(!p.isIncomplete());
931 p= my.getPrimitiveById(3,OsmPrimitiveType.WAY);
932 assertNotNull(p);
933 assertTrue(!p.isIncomplete());
934
935 Way w = (Way)my.getPrimitiveById(3,OsmPrimitiveType.WAY);
936 assertNotNull(w);
937 assertTrue(!p.isIncomplete());
938 assertEquals(2, w.getNodesCount());
939 assertTrue(!w.getNode(0).isIncomplete());
940 assertTrue(!w.getNode(1).isIncomplete());
941 }
942
943 /**
944 * merge to complete nodes onto an incomplete way with the same two nodes, but incomplete.
945 * => both the nodes and the way should be complete in the target dataset after merging
946 */
947 @Test
948 public void twoCompleteNodesOntoAnIncompleteWay() {
949
950 // -- source dataset
951
952 // an complete node
953 Node n1 = new Node(1, 1);
954 n1.setCoor(new LatLon(1,1));
955 their.addPrimitive(n1);
956
957 // another complete node
958 Node n2 = new Node(2, 1);
959 n2.setCoor(new LatLon(2,2));
960 their.addPrimitive(n2);
961
962 // --- target dataset
963
964 Node n4 = new Node(1);
965 my.addPrimitive(n4);
966
967 Node n5 = new Node(2);
968 my.addPrimitive(n5);
969
970 Way w6 = new Way(3, 1);
971 w6.addNode(n4);
972 w6.addNode(n5);
973 my.addPrimitive(w6);
974
975 //-- merge it
976 DataSetMerger visitor = new DataSetMerger(my, their);
977 visitor.merge();
978
979 // -- test it
980 assertEquals(0,visitor.getConflicts().size());
981
982 Node n = (Node)my.getPrimitiveById(1, OsmPrimitiveType.NODE);
983 assertNotNull(n);
984 assertFalse(n.isIncomplete());
985
986 n = (Node)my.getPrimitiveById(2, OsmPrimitiveType.NODE);
987 assertNotNull(n);
988 assertFalse(n.isIncomplete());
989
990 Way w = (Way)my.getPrimitiveById(3, OsmPrimitiveType.WAY);
991 assertNotNull(w);
992 assertFalse(w.hasIncompleteNodes());
993 assertTrue(w.isUsable());
994 assertEquals(2, w.getNodesCount());
995 assertEquals(1, w.getNode(0).getId());
996 assertEquals(2, w.getNode(1).getId());
997 }
998}
Note: See TracBrowser for help on using the repository browser.