source: josm/trunk/src/org/openstreetmap/josm/data/osm/visitor/MergeSourceBuildingVisitor.java@ 5360

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

fix #7776 - Selection of deleted objects

  • Property svn:eol-style set to native
File size: 6.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.data.osm.visitor;
3
4import java.util.ArrayList;
5import java.util.HashMap;
6import java.util.List;
7
8import org.openstreetmap.josm.data.osm.DataSet;
9import org.openstreetmap.josm.data.osm.Node;
10import org.openstreetmap.josm.data.osm.NodeData;
11import org.openstreetmap.josm.data.osm.OsmPrimitive;
12import org.openstreetmap.josm.data.osm.PrimitiveData;
13import org.openstreetmap.josm.data.osm.Relation;
14import org.openstreetmap.josm.data.osm.RelationData;
15import org.openstreetmap.josm.data.osm.RelationMember;
16import org.openstreetmap.josm.data.osm.RelationMemberData;
17import org.openstreetmap.josm.data.osm.Way;
18import org.openstreetmap.josm.data.osm.WayData;
19import org.openstreetmap.josm.tools.CheckParameterUtil;
20
21/**
22 * MergeSourceBuildingVisitor helps to build the "hull" of a collection of {@link OsmPrimitive}s
23 * which shall be merged into another layer. The "hull" is slightly bigger than the original
24 * collection. It includes, for instance the nodes of a way in the original collection even though
25 * these nodes might not be present explicitly in the original collection. The "hull" also includes
26 * incomplete {@link OsmPrimitive}s which are referred to by relations in the original collection. And
27 * it turns {@link OsmPrimitive} referred to by {@link Relation}s in the original collection into
28 * incomplete {@link OsmPrimitive}s in the "hull", if they are not themselves present in the
29 * original collection.
30 *
31 */
32public class MergeSourceBuildingVisitor extends AbstractVisitor {
33 private DataSet selectionBase;
34 private DataSet hull;
35 private HashMap<OsmPrimitive, PrimitiveData> mappedPrimitives;
36
37 /**
38 * Creates the visitor. The visitor starts to build the "hull" from
39 * the currently selected primitives in the dataset <code>selectionBase</code>,
40 * i.e. from {@link DataSet#getSelected()}.
41 *
42 * @param selectionBase the dataset. Must not be null.
43 * @exception IllegalArgumentException thrown if selectionBase is null
44 *
45 */
46 public MergeSourceBuildingVisitor(DataSet selectionBase) throws IllegalArgumentException {
47 CheckParameterUtil.ensureParameterNotNull(selectionBase, "selectionBase");
48 this.selectionBase = selectionBase;
49 this.hull = new DataSet();
50 this.mappedPrimitives = new HashMap<OsmPrimitive, PrimitiveData>();
51 }
52
53 protected boolean isInSelectionBase(OsmPrimitive primitive) {
54 return selectionBase.getAllSelected().contains(primitive);
55 }
56
57 protected boolean isAlreadyRemembered(OsmPrimitive primitive) {
58 return mappedPrimitives.keySet().contains(primitive);
59 }
60
61 /**
62 * Remebers a node in the "hull"
63 *
64 * @param n the node
65 */
66 protected void rememberNode(Node n) {
67 if (isAlreadyRemembered(n))
68 return;
69 mappedPrimitives.put(n, n.save());
70 }
71
72 /**
73 * remembers a way in the hull
74 *
75 * @param w the way
76 */
77 protected void rememberWay(Way w) {
78 if (isAlreadyRemembered(w))
79 return;
80 WayData clone = w.save();
81 List<Long> newNodes = new ArrayList<Long>(w.getNodesCount());
82 for (Node n: w.getNodes()) {
83 newNodes.add(mappedPrimitives.get(n).getUniqueId());
84 }
85 clone.setNodes(newNodes);
86 mappedPrimitives.put(w, clone);
87 }
88
89 /**
90 * Remembers a relation in the hull
91 *
92 * @param r the relation
93 */
94 protected void rememberRelation(Relation r) {
95 RelationData clone;
96 if (isAlreadyRemembered(r)) {
97 clone = (RelationData)mappedPrimitives.get(r);
98 } else {
99 clone = r.save();
100 mappedPrimitives.put(r, clone);
101 }
102
103 List<RelationMemberData> newMembers = new ArrayList<RelationMemberData>();
104 for (RelationMember member: r.getMembers()) {
105 newMembers.add(
106 new RelationMemberData(member.getRole(), mappedPrimitives.get(member.getMember())));
107
108 }
109 clone.setMembers(newMembers);
110 }
111
112 protected void rememberRelationPartial(Relation r) {
113 if (isAlreadyRemembered(r))
114 return;
115 RelationData clone = r.save();
116 clone.getMembers().clear();
117 mappedPrimitives.put(r, clone);
118 }
119
120 protected void rememberIncomplete(OsmPrimitive primitive) {
121 if (isAlreadyRemembered(primitive))
122 return;
123 PrimitiveData clone = primitive.save();
124 clone.setIncomplete(true);
125 mappedPrimitives.put(primitive, clone);
126 }
127
128 public void visit(Node n) {
129 rememberNode(n);
130 }
131
132 public void visit(Way w) {
133 // remember all nodes this way refers to ...
134 //
135 for (Node n: w.getNodes()) {
136 n.visit(this);
137 }
138 // ... and the way itself
139 rememberWay(w);
140 }
141
142 public void visit(Relation r) {
143 // first, remember all primitives members refer to (only if necessary, see
144 // below)
145 //
146 rememberRelationPartial(r);
147 for (RelationMember member: r.getMembers()) {
148 if (isAlreadyRemembered(member.getMember())) {
149 // referred primitive already remembered
150 //
151 continue;
152 }
153 if (isInSelectionBase(member.getMember()) || member.getMember().isNew()) {
154 member.getMember().visit(this);
155 } else {
156 rememberIncomplete(member.getMember());
157 }
158 }
159 rememberRelation(r);
160 }
161
162 protected void buildHull() {
163 // Create all primitives first
164 for (PrimitiveData primitive: mappedPrimitives.values()) {
165 OsmPrimitive newPrimitive = hull.getPrimitiveById(primitive);
166 boolean created = newPrimitive == null;
167 if (created) {
168 newPrimitive = primitive.getType().newInstance(primitive.getUniqueId(), true);
169 }
170 if (newPrimitive instanceof Node && !primitive.isIncomplete()) {
171 newPrimitive.load(primitive);
172 }
173 if (created) {
174 hull.addPrimitive(newPrimitive);
175 }
176 }
177 // Then ways and relations
178 for (PrimitiveData primitive : mappedPrimitives.values()) {
179 if (!(primitive instanceof NodeData) && !primitive.isIncomplete()) {
180 hull.getPrimitiveById(primitive).load(primitive);
181 }
182 }
183 }
184
185 public DataSet build() {
186 for (OsmPrimitive primitive: selectionBase.getAllSelected()) {
187 primitive.visit(this);
188 }
189 buildHull();
190 return hull;
191 }
192}
Note: See TracBrowser for help on using the repository browser.