Ticket #18970: 18970.2.patch
| File 18970.2.patch, 13.3 KB (added by , 6 years ago) |
|---|
-
src/org/openstreetmap/josm/data/osm/AbstractPrimitive.java
127 127 protected static final short FLAG_PRESERVED = 1 << 13; 128 128 129 129 /** 130 * Determines if the primitive refers to incomplete members 131 * Members can be nodes of a way or members of a relation. 132 */ 133 protected static final short FLAG_INCOMPLETE_MEMBERS = 1 << 14; 134 135 /** 130 136 * Put several boolean flags to one short int field to save memory. 131 137 * Other bits of this field are used in subclasses. 132 138 */ -
src/org/openstreetmap/josm/data/osm/Node.java
434 434 protected void updateDirectionFlags() { 435 435 // Nodes do not need/have a direction, greatly improves performance, see #18886 436 436 } 437 438 @Override 439 void childIncompleteStatusWillChange(OsmPrimitive osmPrimitive) { 440 // should not happen, nodes don't have children 441 } 437 442 } -
src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
485 485 checkDatasetNotReadOnly(); 486 486 boolean locked = writeLock(); 487 487 try { 488 if (dataSet != null && incomplete != this.isIncomplete()) { 489 if (incomplete) { 490 dataSet.firePrimitivesRemoved(Collections.singletonList(this), true); 491 } else { 492 dataSet.firePrimitivesAdded(Collections.singletonList(this), true); 488 if (incomplete != this.isIncomplete()) { 489 referrers(true, OsmPrimitive.class).forEach(ref -> ref.childIncompleteStatusWillChange(this)); 490 if (dataSet != null) { 491 if (incomplete) { 492 dataSet.firePrimitivesRemoved(Collections.singletonList(this), true); 493 } else { 494 dataSet.firePrimitivesAdded(Collections.singletonList(this), true); 495 } 493 496 } 494 497 } 495 498 super.setIncomplete(incomplete); … … 498 501 } 499 502 } 500 503 504 /** 505 * Called when the incomplete status of the primitive was changed. 506 * @param osmPrimitive before the change 507 */ 508 abstract void childIncompleteStatusWillChange(OsmPrimitive osmPrimitive); 509 501 510 @Override 502 511 public boolean isSelected() { 503 512 return dataSet != null && dataSet.isSelected(this); … … 837 846 OsmPrimitive[] refs = (OsmPrimitive[]) this.referrers; 838 847 for (OsmPrimitive ref: refs) { 839 848 if (ref.dataSet == dataSet) { 840 visitor.accept(ref);841 849 } 850 visitor.accept(ref); 842 851 } 843 852 } 844 853 } -
src/org/openstreetmap/josm/data/osm/Relation.java
54 54 } else { 55 55 this.members = new RelationMember[0]; 56 56 } 57 boolean hasIncompleteMember = false; 57 58 for (RelationMember rm : this.members) { 58 59 rm.getMember().addReferrer(this); 59 60 rm.getMember().clearCachedStyle(); 61 hasIncompleteMember |= (rm.getMember().isIncomplete()); 60 62 } 61 63 setIncompleteMembers(hasIncompleteMember); 62 64 fireMembersChanged(); 63 65 } finally { 64 66 writeUnlock(locked); … … 84 86 boolean locked = writeLock(); 85 87 try { 86 88 members = Utils.addInArrayCopy(members, member); 89 if (member.getMember().isIncomplete()) 90 setIncompleteMembers(true); 87 91 member.getMember().addReferrer(this); 88 92 member.getMember().clearCachedStyle(); 89 93 fireMembersChanged(); … … 106 110 System.arraycopy(members, index, newMembers, index + 1, members.length - index); 107 111 newMembers[index] = member; 108 112 members = newMembers; 113 if (member.getMember().isIncomplete()) 114 setIncompleteMembers(true); 109 115 member.getMember().addReferrer(this); 110 116 member.getMember().clearCachedStyle(); 111 117 fireMembersChanged(); … … 129 135 if (originalMember.getMember() != member.getMember()) { 130 136 member.getMember().addReferrer(this); 131 137 member.getMember().clearCachedStyle(); 138 if (!originalMember.getMember().isIncomplete() && member.getMember().isIncomplete()) 139 setIncompleteMembers(true); 140 else if (originalMember.getMember().isIncomplete() && !member.getMember().isIncomplete()) { 141 setIncompleteMembers(Stream.of(members).anyMatch(m -> m.getMember().isIncomplete())); 142 } 132 143 originalMember.getMember().removeReferrer(this); 133 144 originalMember.getMember().clearCachedStyle(); 134 145 fireMembersChanged(); … … 493 504 } 494 505 } 495 506 507 /** 508 * If set to true, this object refers to one or more incomplete members. 509 * Members can be nodes of a way or members of a relation. 510 * @param incomplete incomplete flag value 511 */ 512 private void setIncompleteMembers(boolean incomplete) { 513 updateFlags(FLAG_INCOMPLETE_MEMBERS, incomplete); 514 } 515 496 516 @Override 497 517 public boolean hasIncompleteMembers() { 498 for (RelationMember rm: members) { 499 if (rm.getMember().isIncomplete()) return true; 500 } 501 return false; 518 return (flags & FLAG_INCOMPLETE_MEMBERS) != 0; 502 519 } 503 520 504 521 /** … … 508 525 */ 509 526 @Override 510 527 public Collection<OsmPrimitive> getIncompleteMembers() { 511 Set<OsmPrimitive> ret = new HashSet<>(); 512 for (RelationMember rm: members) { 513 if (!rm.getMember().isIncomplete()) { 514 continue; 528 return Stream.of(members).map(RelationMember::getMember).filter(OsmPrimitive::isIncomplete) 529 .collect(Collectors.toSet()); 530 } 531 532 @Override 533 void childIncompleteStatusWillChange(OsmPrimitive osmPrimitive) { 534 for (RelationMember originalMember : getMembersFor(Collections.singleton(osmPrimitive))) { 535 if (!originalMember.getMember().isIncomplete()) 536 setIncompleteMembers(true); 537 else if (originalMember.getMember().isIncomplete()) { 538 setIncompleteMembers(Stream.of(members).filter(m -> m != originalMember) 539 .anyMatch(m -> m.getMember().isIncomplete())); 515 540 } 516 ret.add(rm.getMember());517 541 } 518 return ret;519 542 } 520 543 521 544 @Override -
src/org/openstreetmap/josm/data/osm/Way.java
56 56 } else { 57 57 this.nodes = nodes.toArray(new Node[0]); 58 58 } 59 boolean hasIncompleteNodes = false; 59 60 for (Node node: this.nodes) { 60 61 node.addReferrer(this); 61 62 node.clearCachedStyle(); 63 hasIncompleteNodes |= node.isIncomplete(); 62 64 } 65 setIncompleteNodes(hasIncompleteNodes); 63 66 64 67 clearCachedStyle(); 65 68 fireNodesChanged(); … … 69 72 } 70 73 71 74 /** 75 * If set to true, this object refers to one or more incomplete members. 76 * Members can be nodes of a way or members of a relation. 77 * @param incomplete incomplete flag value 78 */ 79 private void setIncompleteNodes(boolean incomplete) { 80 updateFlags(FLAG_INCOMPLETE_MEMBERS, incomplete); 81 } 82 83 /** 72 84 * Prevent directly following identical nodes in ways. 73 85 * @param nodes list of nodes 74 86 * @return {@code nodes} with consecutive identical nodes removed … … 401 413 clearCachedStyle(); 402 414 n.addReferrer(this); 403 415 nodes = Utils.addInArrayCopy(nodes, n); 416 if (n.isIncomplete()) 417 setIncompleteNodes(true); 404 418 n.clearCachedStyle(); 405 419 fireNodesChanged(); 406 420 } finally { … … 434 448 System.arraycopy(nodes, offs, newNodes, offs + 1, nodes.length - offs); 435 449 newNodes[offs] = n; 436 450 nodes = newNodes; 451 if (n.isIncomplete()) 452 setIncompleteNodes(true); 437 453 n.clearCachedStyle(); 438 454 fireNodesChanged(); 439 455 } finally { … … 590 606 * @since 2587 591 607 */ 592 608 public boolean hasIncompleteNodes() { 593 return Arrays.stream(nodes).anyMatch(Node::isIncomplete);609 return (flags & FLAG_INCOMPLETE_MEMBERS) != 0; 594 610 } 595 611 596 612 /** … … 755 771 public UniqueIdGenerator getIdGenerator() { 756 772 return idGenerator; 757 773 } 774 775 @Override 776 void childIncompleteStatusWillChange(OsmPrimitive osmPrimitive) { 777 if (hasIncompleteNodes() && osmPrimitive.isIncomplete()) { 778 for (Node n : nodes) { 779 if (n != osmPrimitive && n.isIncomplete()) { 780 setIncomplete(true); 781 break; 782 } 783 } 784 } 785 } 758 786 } -
test/unit/org/openstreetmap/josm/data/osm/RelationTest.java
154 154 public void testLoadIAE() { 155 155 new Relation().load(new NodeData()); 156 156 } 157 158 /** 159 * Test {@link Relation#hasIncompleteNodes()} 160 */ 161 @Test 162 public void testIncompleteMembers() { 163 DataSet ds = new DataSet(); 164 165 Node n1 = new Node(new LatLon(10, 10)); 166 Node n2 = new Node(new LatLon(20, 20)); 167 Way w1 = new Way(); 168 w1.addNode(n1); 169 w1.addNode(n2); 170 Relation r1 = new Relation(); 171 ds.addPrimitive(r1); 172 ds.addPrimitive(n1); 173 ds.addPrimitive(n2); 174 ds.addPrimitive(w1); 175 r1.addMember(new RelationMember("", n1)); 176 r1.addMember(new RelationMember("", w1)); 177 r1.addMember(new RelationMember("", r1)); 178 assertFalse(r1.hasIncompleteMembers()); 179 Node n3 = new Node(1); // incomplete node 180 ds.addPrimitive(n3); 181 r1.addMember(new RelationMember("", n3)); 182 assertTrue(r1.hasIncompleteMembers()); 183 r1.removeMembersFor(n3); 184 assertFalse(r1.hasIncompleteMembers()); 185 r1.addMember(1, new RelationMember("", n3)); 186 assertTrue(r1.hasIncompleteMembers()); 187 r1.removeMember(1); 188 assertFalse(r1.hasIncompleteMembers()); 189 r1.addMember(1, new RelationMember("", n3)); 190 assertTrue(r1.hasIncompleteMembers()); 191 r1.setMember(1, new RelationMember("", n2)); 192 assertFalse(r1.hasIncompleteMembers()); 193 r1.setMember(1, new RelationMember("", n3)); 194 assertTrue(r1.hasIncompleteMembers()); 195 n3.setCoor(new LatLon(30, 30)); 196 n3.setIncomplete(false); 197 assertFalse(r1.hasIncompleteMembers()); 198 } 199 157 200 } -
test/unit/org/openstreetmap/josm/data/osm/WayTest.java
64 64 } 65 65 66 66 /** 67 * Test that {@link Way#load} throws IAE for invalid arguments67 * Test {@link Way#hasIncompleteNodes()} 68 68 */ 69 @Test(expected = IllegalArgumentException.class) 70 public void testLoadIAE() { 71 new Way().load(new NodeData()); 69 @Test 70 public void testIncompleteNodes() { 71 DataSet ds = new DataSet(); 72 Node n1 = new Node(1); 73 Node n2 = new Node(2); 74 n1.setIncomplete(true); 75 n2.setCoor(new LatLon(20, 20)); 76 n2.setIncomplete(false); 77 Way way = new Way(1); 78 way.setIncomplete(false); 79 ds.addPrimitive(n1); 80 ds.addPrimitive(n2); 81 ds.addPrimitive(way); 82 assertFalse(way.hasIncompleteNodes()); 83 way.setNodes(Arrays.asList(n1)); 84 assertTrue(way.hasIncompleteNodes()); 85 way.setNodes(Arrays.asList(n2)); 86 assertFalse(way.hasIncompleteNodes()); 87 way.setNodes(Arrays.asList(n1, n2)); 88 assertTrue(way.hasIncompleteNodes()); 89 way.removeNode(n1); 90 assertFalse(way.hasIncompleteNodes()); 91 way.addNode(n1); 92 assertTrue(way.hasIncompleteNodes()); 93 n1.setCoor(new LatLon(10, 10)); 94 n1.setIncomplete(false); 95 assertFalse(way.hasIncompleteNodes()); 72 96 } 73 97 }
