source: josm/trunk/src/org/openstreetmap/josm/data/osm/Relation.java@ 2620

Last change on this file since 2620 was 2620, checked in by jttt, 14 years ago

Remove OsmPrimitive.setIncomplete()

  • Property svn:eol-style set to native
File size: 9.7 KB
Line 
1package org.openstreetmap.josm.data.osm;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.HashSet;
6import java.util.List;
7import java.util.Set;
8
9import org.openstreetmap.josm.data.osm.visitor.Visitor;
10import org.openstreetmap.josm.tools.CopyList;
11
12/**
13 * An relation, having a set of tags and any number (0...n) of members.
14 *
15 * @author Frederik Ramm <frederik@remote.org>
16 */
17public final class Relation extends OsmPrimitive {
18
19 /**
20 * All members of this relation. Note that after changing this,
21 * makeBackReferences and/or removeBackReferences should be called.
22 *
23 */
24 private final List<RelationMember> members = new ArrayList<RelationMember>();
25
26 /**
27 * @return Members of the relation. Changes made in returned list are not mapped
28 * back to the primitive, use setMembers() to modify the members
29 * @since 1925
30 */
31 public List<RelationMember> getMembers() {
32 return new CopyList<RelationMember>(members.toArray(new RelationMember[members.size()]));
33 }
34
35 /**
36 *
37 * @param members Can be null, in that case all members are removed
38 * @since 1925
39 */
40 public void setMembers(List<RelationMember> members) {
41 for (RelationMember rm:this.members) {
42 rm.getMember().removeReferrer(this);
43 }
44
45 this.members.clear();
46 if (members != null) {
47 this.members.addAll(members);
48 }
49 for (RelationMember rm:this.members) {
50 rm.getMember().addReferrer(this);
51 }
52
53 fireMembersChanged();
54 }
55
56 /**
57 *
58 * @since 1926
59 */
60 public int getMembersCount() {
61 return members.size();
62 }
63
64 /**
65 *
66 * @param index
67 * @return
68 * @since 1926
69 */
70 public RelationMember getMember(int index) {
71 return members.get(index);
72 }
73
74 /**
75 *
76 * @param member
77 * @since 1951
78 */
79 public void addMember(RelationMember member) {
80 members.add(member);
81 member.getMember().addReferrer(this);
82 fireMembersChanged();
83 }
84
85 /**
86 *
87 * @param index
88 * @param member
89 * @since 1951
90 */
91 public void addMember(int index, RelationMember member) {
92 members.add(index, member);
93 member.getMember().addReferrer(this);
94 fireMembersChanged();
95 }
96
97 /**
98 * Replace member at position specified by index.
99 * @param index
100 * @param member
101 * @return Member that was at the position
102 * @since 1951
103 */
104 public RelationMember setMember(int index, RelationMember member) {
105 RelationMember result = members.set(index, member);
106 if (result.getMember() != member.getMember()) {
107 member.getMember().addReferrer(this);
108 result.getMember().removeReferrer(this);
109 fireMembersChanged();
110 }
111 return result;
112 }
113
114 /**
115 * Removes member at specified position.
116 * @param index
117 * @return Member that was at the position
118 * @since 1951
119 */
120 public RelationMember removeMember(int index) {
121 RelationMember result = members.remove(index);
122 for (RelationMember rm:members) {
123 // Do not remove referrer if this primitive is used in relation twice
124 if (rm.getMember() == result.getMember())
125 return result;
126 }
127 result.getMember().removeReferrer(this);
128 fireMembersChanged();
129 return result;
130 }
131
132 @Override public void visit(Visitor visitor) {
133 visitor.visit(this);
134 }
135
136 protected Relation(long id, boolean allowNegative) {
137 super(id, allowNegative);
138 }
139
140 /**
141 * Create a new relation with id 0
142 */
143 public Relation() {
144 super(0, false);
145 }
146
147 public Relation(Relation clone, boolean clearId) {
148 super(clone.getUniqueId(), true);
149 cloneFrom(clone);
150 if (clearId) {
151 clearOsmId();
152 }
153 }
154
155 /**
156 * Create an identical clone of the argument (including the id)
157 */
158 public Relation(Relation clone) {
159 this(clone, false);
160 }
161
162 /**
163 * Creates a new relation for the given id. If the id > 0, the way is marked
164 * as incomplete.
165 *
166 * @param id the id. > 0 required
167 * @throws IllegalArgumentException thrown if id < 0
168 */
169 public Relation(long id) throws IllegalArgumentException {
170 super(id, false);
171 }
172
173 /**
174 * Creates new complete relation
175 * @param id
176 * @param version
177 */
178 public Relation(long id, int version) {
179 super(id, false);
180 setOsmId(id, version);
181 }
182
183 @Override public void cloneFrom(OsmPrimitive osm) {
184 super.cloneFrom(osm);
185 // It's not necessary to clone members as RelationMember class is immutable
186 setMembers(((Relation)osm).getMembers());
187 }
188
189 @Override public void load(PrimitiveData data) {
190 super.load(data);
191
192 RelationData relationData = (RelationData) data;
193
194 List<RelationMember> newMembers = new ArrayList<RelationMember>();
195 for (RelationMemberData member : relationData.getMembers()) {
196 OsmPrimitive primitive = getDataSet().getPrimitiveById(member);
197 if (primitive == null)
198 throw new AssertionError("Data consistency problem - relation with missing member detected");
199 newMembers.add(new RelationMember(member.getRole(), primitive));
200 }
201 setMembers(newMembers);
202 }
203
204 @Override public RelationData save() {
205 RelationData data = new RelationData();
206 saveCommonAttributes(data);
207 for (RelationMember member:getMembers()) {
208 data.getMembers().add(new RelationMemberData(member.getRole(), member.getMember()));
209 }
210 return data;
211 }
212
213 @Override public String toString() {
214 StringBuilder result = new StringBuilder();
215 result.append("{Relation id=");
216 result.append(getUniqueId());
217 result.append(" version=");
218 result.append(getVersion());
219 result.append(" [");
220 for (RelationMember rm:getMembers()) {
221 result.append(OsmPrimitiveType.from(rm.getMember()));
222 result.append(" ");
223 result.append(rm.getMember().getUniqueId());
224 result.append(", ");
225 }
226 result.delete(result.length()-2, result.length());
227 result.append("]");
228 result.append("}");
229 return result.toString();
230 }
231
232 @Override
233 public boolean hasEqualSemanticAttributes(OsmPrimitive other) {
234 if (other == null || ! (other instanceof Relation) )
235 return false;
236 if (! super.hasEqualSemanticAttributes(other))
237 return false;
238 Relation r = (Relation)other;
239 return members.equals(r.members);
240 }
241
242 public int compareTo(OsmPrimitive o) {
243 return o instanceof Relation ? Long.valueOf(getUniqueId()).compareTo(o.getUniqueId()) : -1;
244 }
245
246 public RelationMember firstMember() {
247 if (isIncomplete()) return null;
248 return (members.size() == 0) ? null : members.get(0);
249 }
250 public RelationMember lastMember() {
251 if (isIncomplete()) return null;
252 return (members.size() == 0) ? null : members.get(members.size() -1);
253 }
254
255 /**
256 * removes all members with member.member == primitive
257 *
258 * @param primitive the primitive to check for
259 */
260 public void removeMembersFor(OsmPrimitive primitive) {
261 if (primitive == null)
262 return;
263
264 ArrayList<RelationMember> todelete = new ArrayList<RelationMember>();
265 for (RelationMember member: members) {
266 if (member.getMember() == primitive) {
267 todelete.add(member);
268 }
269 }
270 primitive.removeReferrer(this);
271 members.removeAll(todelete);
272 fireMembersChanged();
273 }
274
275 @Override
276 public void setDeleted(boolean deleted) {
277 for (RelationMember rm:members) {
278 if (deleted) {
279 rm.getMember().removeReferrer(this);
280 } else {
281 rm.getMember().addReferrer(this);
282 }
283 }
284 super.setDeleted(deleted);
285 }
286
287 /**
288 * removes all members with member.member == primitive
289 *
290 * @param primitives the primitives to check for
291 */
292 public void removeMembersFor(Collection<OsmPrimitive> primitives) {
293 if (primitives == null || primitives.isEmpty())
294 return;
295
296 ArrayList<RelationMember> todelete = new ArrayList<RelationMember>();
297 for (RelationMember member: members) {
298 if (primitives.contains(member.getMember())) {
299 todelete.add(member);
300 }
301 }
302 members.removeAll(todelete);
303 for (OsmPrimitive primitive:primitives) {
304 primitive.removeReferrer(this);
305 }
306 fireMembersChanged();
307 }
308
309 @Override
310 public String getDisplayName(NameFormatter formatter) {
311 return formatter.format(this);
312 }
313
314 /**
315 * Replies the set of {@see OsmPrimitive}s referred to by at least one
316 * member of this relation
317 *
318 * @return the set of {@see OsmPrimitive}s referred to by at least one
319 * member of this relation
320 */
321 public Set<OsmPrimitive> getMemberPrimitives() {
322 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
323 for (RelationMember m: members) {
324 if (m.getMember() != null) {
325 ret.add(m.getMember());
326 }
327 }
328 return ret;
329 }
330
331 public OsmPrimitiveType getType() {
332 return OsmPrimitiveType.RELATION;
333 }
334
335 @Override
336 public BBox getBBox() {
337 return new BBox(0, 0, 0, 0);
338 }
339
340 @Override
341 public void updatePosition() {
342 // Do nothing for now
343 }
344
345 private void fireMembersChanged() {
346 if (getDataSet() != null) {
347 getDataSet().fireRelationMembersChanged(this);
348 }
349 }
350}
Note: See TracBrowser for help on using the repository browser.