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

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

Sonar - remove warnings related to the static preferences initialization in instance methods

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