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

Last change on this file since 7937 was 7937, checked in by bastiK, 9 years ago

add subversion property svn:eol=native

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