Relation.java (3208B) download
1package osm.message;
2
3import java.util.ArrayList;
4import java.util.Iterator;
5import java.util.List;
6import java.util.function.Supplier;
7
8import protobuf.ProtobufReader;
9
10// enum MemberType {
11// NODE = 0;
12// WAY = 1;
13// RELATION = 2;
14// }
15// required int64 id = 1;
16// repeated uint32 keys = 2 [packed = true];
17// repeated uint32 vals = 3 [packed = true];
18// optional Info info = 4;
19// repeated int32 roles_sid = 8 [packed = true]; // This should have been defined as uint32 for consistency, but it is now too late to change it
20// repeated sint64 memids = 9 [packed = true]; // DELTA encoded
21// repeated MemberType types = 10 [packed = true];
22public class Relation extends AbstractEntity<Relation> {
23 public static enum RelationMemberType {
24 NODE, WAY, RELATION
25 }
26
27 public static class RelationMember {
28 private RelationMemberType type;
29 private long id;
30 private String role;
31
32 public RelationMemberType getType() {
33 return type;
34 }
35
36 public long getID() {
37 return id;
38 }
39
40 public String getRole() {
41 return role;
42 }
43 }
44
45 private List<RelationMember> members = new ArrayList<>();
46
47 public Relation(PrimitiveBlock block) {
48 super(block);
49 }
50
51 private <T> void expandList(List<T> list, int index, Supplier<T> with) {
52 while (list.size() <= index)
53 list.add(with.get());
54 }
55
56 @Override
57 public Relation parseRemaining(Iterator<ProtobufReader> tags) {
58 int indexRole = 0,
59 indexID = 0,
60 indexType = 0;
61
62 while (tags.hasNext()) {
63 ProtobufReader message = tags.next();
64 switch (message.tag()) {
65 case 4:
66 message.skip();
67 break;
68 case 8:
69 Iterator<Integer> roles = message.packed(message::varint32);
70 while (roles.hasNext()) {
71 expandList(members, indexRole, RelationMember::new);
72
73 members.get(indexRole).role = block.stringtable.get(roles.next());
74 indexRole++;
75 }
76 break;
77 case 9:
78 Iterator<Long> ids = message.packed(message::svarint64, 0L, Long::sum);
79 while (ids.hasNext()) {
80 expandList(members, indexID, RelationMember::new);
81
82 members.get(indexID).id = ids.next();
83 indexID++;
84 }
85 break;
86 case 10:
87 Iterator<Integer> types = message.packed(message::varint32);
88 while (types.hasNext()) {
89 expandList(members, indexType, RelationMember::new);
90
91 members.get(indexType).type = RelationMemberType.values()[types.next()];
92 indexType++;
93 }
94 break;
95 default:
96 message.throwUnexpected();
97 }
98 }
99 return this;
100 }
101
102 public List<RelationMember> getMembers() {
103 return members;
104 }
105}