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

Last change on this file since 2555 was 2555, checked in by stoecker, 14 years ago

fixed #4055 - patch my mjulius - fix object compare

  • Property svn:eol-style set to native
File size: 9.8 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 @Override public void cloneFrom(OsmPrimitive osm) {
174 super.cloneFrom(osm);
175 // It's not necessary to clone members as RelationMember class is immutable
176 setMembers(((Relation)osm).getMembers());
177 }
178
179 @Override public void load(PrimitiveData data) {
180 super.load(data);
181
182 RelationData relationData = (RelationData) data;
183
184 List<RelationMember> newMembers = new ArrayList<RelationMember>();
185 for (RelationMemberData member : relationData.getMembers()) {
186 OsmPrimitive primitive = getDataSet().getPrimitiveById(member);
187 if (primitive == null)
188 throw new AssertionError("Data consistency problem - relation with missing member detected");
189 newMembers.add(new RelationMember(member.getRole(), primitive));
190 }
191 setMembers(newMembers);
192 }
193
194 @Override public RelationData save() {
195 RelationData data = new RelationData();
196 saveCommonAttributes(data);
197 for (RelationMember member:getMembers()) {
198 data.getMembers().add(new RelationMemberData(member.getRole(), member.getMember()));
199 }
200 return data;
201 }
202
203 @Override public String toString() {
204 StringBuilder result = new StringBuilder();
205 result.append("{Relation id=");
206 result.append(getUniqueId());
207 result.append(" version=");
208 result.append(getVersion());
209 result.append(" [");
210 for (RelationMember rm:getMembers()) {
211 result.append(OsmPrimitiveType.from(rm.getMember()));
212 result.append(" ");
213 result.append(rm.getMember().getUniqueId());
214 result.append(", ");
215 }
216 result.delete(result.length()-2, result.length());
217 result.append("]");
218 result.append("}");
219 return result.toString();
220 }
221
222 @Override
223 public boolean hasEqualSemanticAttributes(OsmPrimitive other) {
224 if (other == null || ! (other instanceof Relation) )
225 return false;
226 if (! super.hasEqualSemanticAttributes(other))
227 return false;
228 Relation r = (Relation)other;
229 return members.equals(r.members);
230 }
231
232 public int compareTo(OsmPrimitive o) {
233 return o instanceof Relation ? Long.valueOf(getUniqueId()).compareTo(o.getUniqueId()) : -1;
234 }
235
236 // seems to be different from member "incomplete" - FIXME
237 public boolean isIncomplete() {
238 for (RelationMember m : members)
239 if (m.getMember() == null)
240 return true;
241 return false;
242 }
243
244 public RelationMember firstMember() {
245 if (incomplete) return null;
246 return (members.size() == 0) ? null : members.get(0);
247 }
248 public RelationMember lastMember() {
249 if (incomplete) return null;
250 return (members.size() == 0) ? null : members.get(members.size() -1);
251 }
252
253 /**
254 * removes all members with member.member == primitive
255 *
256 * @param primitive the primitive to check for
257 */
258 public void removeMembersFor(OsmPrimitive primitive) {
259 if (primitive == null)
260 return;
261
262 ArrayList<RelationMember> todelete = new ArrayList<RelationMember>();
263 for (RelationMember member: members) {
264 if (member.getMember() == primitive) {
265 todelete.add(member);
266 }
267 }
268 primitive.removeReferrer(this);
269 members.removeAll(todelete);
270 fireMembersChanged();
271 }
272
273 @Override
274 public void setDeleted(boolean deleted) {
275 for (RelationMember rm:members) {
276 if (deleted) {
277 rm.getMember().removeReferrer(this);
278 } else {
279 rm.getMember().addReferrer(this);
280 }
281 }
282 super.setDeleted(deleted);
283 }
284
285 /**
286 * removes all members with member.member == primitive
287 *
288 * @param primitives the primitives to check for
289 */
290 public void removeMembersFor(Collection<OsmPrimitive> primitives) {
291 if (primitives == null || primitives.isEmpty())
292 return;
293
294 ArrayList<RelationMember> todelete = new ArrayList<RelationMember>();
295 for (RelationMember member: members) {
296 if (primitives.contains(member.getMember())) {
297 todelete.add(member);
298 }
299 }
300 members.removeAll(todelete);
301 for (OsmPrimitive primitive:primitives) {
302 primitive.removeReferrer(this);
303 }
304 fireMembersChanged();
305 }
306
307 @Override
308 public String getDisplayName(NameFormatter formatter) {
309 return formatter.format(this);
310 }
311
312 /**
313 * Replies the set of {@see OsmPrimitive}s referred to by at least one
314 * member of this relation
315 *
316 * @return the set of {@see OsmPrimitive}s referred to by at least one
317 * member of this relation
318 */
319 public Set<OsmPrimitive> getMemberPrimitives() {
320 HashSet<OsmPrimitive> ret = new HashSet<OsmPrimitive>();
321 for (RelationMember m: members) {
322 if (m.getMember() != null) {
323 ret.add(m.getMember());
324 }
325 }
326 return ret;
327 }
328
329 public OsmPrimitiveType getType() {
330 return OsmPrimitiveType.RELATION;
331 }
332
333 @Override
334 public BBox getBBox() {
335 return new BBox(0, 0, 0, 0);
336 }
337
338 @Override
339 public void updatePosition() {
340 // Do nothing for now
341 }
342
343 private void fireMembersChanged() {
344 if (getDataSet() != null) {
345 getDataSet().fireRelationMembersChanged(this);
346 }
347 }
348}
Note: See TracBrowser for help on using the repository browser.