source: josm/trunk/test/unit/org/openstreetmap/josm/data/osm/visitor/MergeVisitorTest.java@ 2396

Last change on this file since 2396 was 2396, checked in by Gubaer, 14 years ago

Made nodes, ways, and relations in DataSet private. Plugin updates to be checked in shortly.
Also added setter/getter for DataSet version.

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