aixm 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +14 -3
  4. data/README.md +30 -2
  5. data/exe/ckmid +1 -7
  6. data/exe/mkmid +1 -7
  7. data/lib/aixm/classes.rb +2 -1
  8. data/lib/aixm/component/address.rb +12 -15
  9. data/lib/aixm/component/approach_lighting.rb +11 -16
  10. data/lib/aixm/component/fato.rb +22 -34
  11. data/lib/aixm/component/frequency.rb +10 -15
  12. data/lib/aixm/component/geometry/arc.rb +2 -3
  13. data/lib/aixm/component/geometry/border.rb +6 -10
  14. data/lib/aixm/component/geometry/circle.rb +4 -4
  15. data/lib/aixm/component/geometry/point.rb +4 -4
  16. data/lib/aixm/component/geometry/rhumb_line.rb +4 -4
  17. data/lib/aixm/component/geometry.rb +4 -4
  18. data/lib/aixm/component/helipad.rb +13 -20
  19. data/lib/aixm/component/layer.rb +6 -8
  20. data/lib/aixm/component/lighting.rb +12 -17
  21. data/lib/aixm/component/runway.rb +26 -38
  22. data/lib/aixm/component/service.rb +12 -16
  23. data/lib/aixm/component/surface.rb +8 -10
  24. data/lib/aixm/component/timesheet.rb +9 -10
  25. data/lib/aixm/component/timetable.rb +6 -7
  26. data/lib/aixm/component/vasis.rb +6 -8
  27. data/lib/aixm/component/vertical_limit.rb +8 -8
  28. data/lib/aixm/component.rb +3 -2
  29. data/lib/aixm/concerns/association.rb +381 -0
  30. data/lib/aixm/concerns/memoize.rb +107 -0
  31. data/lib/aixm/concerns/xml_builder.rb +34 -0
  32. data/lib/aixm/document.rb +52 -21
  33. data/lib/aixm/feature/airport.rb +44 -47
  34. data/lib/aixm/feature/airspace.rb +27 -34
  35. data/lib/aixm/feature/generic.rb +67 -0
  36. data/lib/aixm/feature/navigational_aid/designated_point.rb +11 -13
  37. data/lib/aixm/feature/navigational_aid/dme.rb +12 -15
  38. data/lib/aixm/feature/navigational_aid/marker.rb +12 -15
  39. data/lib/aixm/feature/navigational_aid/ndb.rb +13 -16
  40. data/lib/aixm/feature/navigational_aid/tacan.rb +15 -17
  41. data/lib/aixm/feature/navigational_aid/vor.rb +16 -19
  42. data/lib/aixm/feature/navigational_aid.rb +7 -7
  43. data/lib/aixm/feature/obstacle.rb +20 -21
  44. data/lib/aixm/feature/obstacle_group.rb +19 -20
  45. data/lib/aixm/feature/organisation.rb +11 -12
  46. data/lib/aixm/feature/unit.rb +16 -18
  47. data/lib/aixm/feature.rb +26 -7
  48. data/lib/aixm/object.rb +1 -1
  49. data/lib/aixm/refinements.rb +57 -0
  50. data/lib/aixm/version.rb +1 -1
  51. data/lib/aixm.rb +4 -3
  52. data/schemas/ofmx/0.1/OFMX-Snapshot.xsd +6 -1
  53. data.tar.gz.sig +3 -3
  54. metadata +7 -19
  55. metadata.gz.sig +0 -0
  56. data/lib/aixm/association.rb +0 -378
  57. data/lib/aixm/memoize.rb +0 -105
@@ -18,8 +18,7 @@ module AIXM
18
18
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#fls-fato-direction-lighting
19
19
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#tls-helipad-tlof-lighting
20
20
  class Lighting < Component
21
- include AIXM::Association
22
- include AIXM::Memoize
21
+ include AIXM::Concerns::Association
23
22
  include AIXM::Concerns::Intensity
24
23
  include AIXM::Concerns::Remarks
25
24
 
@@ -103,27 +102,23 @@ module AIXM
103
102
  @color = value.nil? ? nil : COLORS.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid color")
104
103
  end
105
104
 
106
- # @return [String] UID markup
107
- def to_uid(as:)
108
- builder = Builder::XmlMarkup.new(indent: 2)
109
- builder.tag!(as) do |tag|
110
- tag << lightable.to_uid.indent(2)
111
- tag.codePsn(POSITIONS.key(position).to_s)
105
+ # @!visibility private
106
+ def add_uid_to(builder, as:)
107
+ builder.send(as) do |tag|
108
+ lightable.add_uid_to(tag)
109
+ tag.codePsn(POSITIONS.key(position))
112
110
  end
113
111
  end
114
- memoize :to_uid
115
112
 
116
- # @return [String] AIXM or OFMX markup
117
- def to_xml(as:)
118
- builder = Builder::XmlMarkup.new(indent: 2)
119
- builder.tag!(as) do |tag|
120
- tag << to_uid(as: "#{as}Uid").indent(2)
113
+ # @!visibility private
114
+ def add_to(builder, as:)
115
+ builder.send(as) do |tag|
116
+ add_uid_to(tag, as: "#{as}Uid")
121
117
  tag.txtDescr(description) if description
122
- tag.codeIntst(INTENSITIES.key(intensity).to_s) if intensity
123
- tag.codeColour(COLORS.key(color).to_s) if color
118
+ tag.codeIntst(INTENSITIES.key(intensity)) if intensity
119
+ tag.codeColour(COLORS.key(color)) if color
124
120
  tag.txtRmk(remarks) if remarks
125
121
  end
126
- builder.target!
127
122
  end
128
123
  end
129
124
  end
@@ -49,8 +49,7 @@ module AIXM
49
49
  #
50
50
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rwy-runway
51
51
  class Runway < Component
52
- include AIXM::Association
53
- include AIXM::Memoize
52
+ include AIXM::Concerns::Association
54
53
  include AIXM::Concerns::Marking
55
54
  include AIXM::Concerns::Remarks
56
55
 
@@ -144,39 +143,33 @@ module AIXM
144
143
  @status = value.nil? ? nil : (STATUSES.lookup(value.to_s.to_sym, nil) || fail(ArgumentError, "invalid status"))
145
144
  end
146
145
 
147
- # @return [String] UID markup
148
- def to_uid
149
- builder = Builder::XmlMarkup.new(indent: 2)
146
+ # @!visibility private
147
+ def add_uid_to(builder)
150
148
  builder.RwyUid do |rwy_uid|
151
- rwy_uid << airport.to_uid.indent(2)
149
+ airport.add_uid_to(rwy_uid)
152
150
  rwy_uid.txtDesig(name)
153
151
  end
154
152
  end
155
- memoize :to_uid
156
153
 
157
- # @return [String] AIXM or OFMX markup
158
- def to_xml
159
- builder = Builder::XmlMarkup.new(indent: 2)
154
+ # @!visibility private
155
+ def add_to(builder)
160
156
  builder.Rwy do |rwy|
161
- rwy << to_uid.indent(2)
157
+ add_uid_to(rwy)
162
158
  if dimensions
163
159
  rwy.valLen(dimensions.length.to_m.dim.trim)
164
160
  rwy.valWid(dimensions.width.to_m.dim.trim)
165
161
  rwy.uomDimRwy('M')
166
162
  end
167
- unless (xml = surface.to_xml).empty?
168
- rwy << xml.indent(2)
169
- end
170
- rwy.codeSts(STATUSES.key(status).to_s) if status
163
+ surface.add_to(rwy) if surface
164
+ rwy.codeSts(STATUSES.key(status)) if status
171
165
  rwy.txtMarking(marking) if marking
172
166
  rwy.txtRmk(remarks) if remarks
173
167
  end
174
168
  %i(@forth @back).each do |direction|
175
169
  if direction = instance_variable_get(direction)
176
- builder << direction.to_xml
170
+ direction.add_to(builder)
177
171
  end
178
172
  end
179
- builder.target!
180
173
  end
181
174
 
182
175
  # Runway directions further describe each direction {#forth} and {#back}
@@ -184,8 +177,9 @@ module AIXM
184
177
  #
185
178
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airport#rdn-runway-direction
186
179
  class Direction
187
- include AIXM::Association
188
- include AIXM::Memoize
180
+ include AIXM::Concerns::Association
181
+ include AIXM::Concerns::Memoize
182
+ include AIXM::Concerns::XMLBuilder
189
183
  include AIXM::Concerns::Remarks
190
184
 
191
185
  VFR_PATTERNS = {
@@ -306,54 +300,48 @@ module AIXM
306
300
  end
307
301
  end
308
302
 
309
- # @return [String] UID markup
310
- def to_uid
311
- builder = Builder::XmlMarkup.new(indent: 2)
303
+ # @!visibility private
304
+ def add_uid_to(builder)
312
305
  builder.RdnUid do |rdn_uid|
313
- rdn_uid << runway.to_uid.indent(2)
306
+ runway.add_uid_to(rdn_uid)
314
307
  rdn_uid.txtDesig(name.to_s(:runway))
315
308
  end
316
309
  end
317
- memoize :to_uid
318
310
 
319
- # @return [String] AIXM or OFMX markup
320
- def to_xml
321
- builder = Builder::XmlMarkup.new(indent: 2)
311
+ # @!visibility private
312
+ def add_to(builder)
322
313
  builder.Rdn do |rdn|
323
- rdn << to_uid.indent(2)
314
+ add_uid_to(rdn)
324
315
  rdn.geoLat(xy.lat(AIXM.schema))
325
316
  rdn.geoLong(xy.long(AIXM.schema))
326
317
  rdn.valTrueBrg(geographic_bearing.to_s(:bearing)) if geographic_bearing
327
318
  rdn.valMagBrg(magnetic_bearing.to_s(:bearing)) if magnetic_bearing
328
319
  if z
329
320
  rdn.valElevTdz(z.alt)
330
- rdn.uomElevTdz(z.unit.upcase.to_s)
331
- end
332
- if vasis
333
- rdn << vasis.to_xml.indent(2)
321
+ rdn.uomElevTdz(z.unit.upcase)
334
322
  end
335
- rdn.codeVfrPattern(VFR_PATTERNS.key(vfr_pattern).to_s) if vfr_pattern
323
+ vasis.add_to(rdn) if vasis
324
+ rdn.codeVfrPattern(VFR_PATTERNS.key(vfr_pattern)) if vfr_pattern
336
325
  rdn.txtRmk(remarks) if remarks
337
326
  end
338
327
  if displaced_threshold
339
328
  builder.Rdd do |rdd|
340
329
  rdd.RddUid do |rdd_uid|
341
- rdd_uid << to_uid.indent(4)
330
+ add_uid_to(rdd_uid)
342
331
  rdd_uid.codeType('DPLM')
343
332
  rdd_uid.codeDayPeriod('A')
344
333
  end
345
334
  rdd.valDist(displaced_threshold.dim.trim)
346
- rdd.uomDist(displaced_threshold.unit.to_s.upcase)
335
+ rdd.uomDist(displaced_threshold.unit.upcase)
347
336
  rdd.txtRmk(remarks) if remarks
348
337
  end
349
338
  end
350
339
  lightings.each do |lighting|
351
- builder << lighting.to_xml(as: :Rls)
340
+ lighting.add_to(builder, as: :Rls)
352
341
  end
353
342
  approach_lightings.each do |approach_lighting|
354
- builder << approach_lighting.to_xml(as: :Rda)
343
+ approach_lighting.add_to(builder, as: :Rda)
355
344
  end
356
- builder.target!
357
345
  end
358
346
  end
359
347
  end
@@ -15,8 +15,7 @@ module AIXM
15
15
  #
16
16
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Organisation#ser-service
17
17
  class Service < Component
18
- include AIXM::Association
19
- include AIXM::Memoize
18
+ include AIXM::Concerns::Association
20
19
  include AIXM::Concerns::Timetable
21
20
  include AIXM::Concerns::Remarks
22
21
 
@@ -183,31 +182,28 @@ module AIXM
183
182
  GUESSED_UNIT_TYPES_MAP[type]
184
183
  end
185
184
 
186
- # @return [String] UID markup
187
- def to_uid
185
+ # @!visibility private
186
+ def add_uid_to(builder)
188
187
  resequence!
189
- builder = Builder::XmlMarkup.new(indent: 2)
190
188
  builder.SerUid do |ser_uid|
191
- ser_uid << unit.to_uid.indent(2)
192
- ser_uid.codeType(TYPES.key(type).to_s)
189
+ unit.add_uid_to(ser_uid)
190
+ ser_uid.codeType(TYPES.key(type))
193
191
  ser_uid.noSeq(@sequence)
194
192
  end
195
193
  end
196
- memoize :to_uid
197
194
 
198
- # @return [String] AIXM or OFMX markup
199
- def to_xml
200
- builder = Builder::XmlMarkup.new(indent: 2)
201
- builder.comment! ["Service: #{TYPES.key(type)}", unit&.send(:name_with_type)].compact.join(' by ')
195
+ # @!visibility private
196
+ def add_to(builder)
197
+ builder.comment ["Service: #{TYPES.key(type)}", unit&.send(:name_with_type)].compact.join(' by ').dress
198
+ builder.text "\n"
202
199
  builder.Ser do |ser|
203
- ser << to_uid.indent(2)
204
- ser << timetable.to_xml(as: :Stt).indent(2) if timetable
200
+ add_uid_to(ser)
201
+ timetable.add_to(ser, as: :Stt) if timetable
205
202
  ser.txtRmk(remarks) if remarks
206
203
  end
207
204
  frequencies.each do |frequency|
208
- builder << frequency.to_xml
205
+ frequency.add_to(builder)
209
206
  end
210
- builder.target!
211
207
  end
212
208
 
213
209
  private
@@ -164,12 +164,11 @@ module AIXM
164
164
  @auw_weight = value
165
165
  end
166
166
 
167
- # @return [String] AIXM or OFMX markup
168
- def to_xml
169
- builder = Builder::XmlMarkup.new(indent: true)
170
- builder.codeComposition(COMPOSITIONS.key(composition).to_s) if composition
171
- builder.codePreparation(PREPARATIONS.key(preparation).to_s) if preparation
172
- builder.codeCondSfc(CONDITIONS.key(condition).to_s) if condition
167
+ # @!visibility private
168
+ def add_to(builder)
169
+ builder.codeComposition(COMPOSITIONS.key(composition)) if composition
170
+ builder.codePreparation(PREPARATIONS.key(preparation)) if preparation
171
+ builder.codeCondSfc(CONDITIONS.key(condition)) if condition
173
172
  if pcn
174
173
  builder.valPcnClass(@pcn['capacity'])
175
174
  builder.codePcnPavementType(@pcn['type'])
@@ -180,17 +179,16 @@ module AIXM
180
179
  builder.txtPcnNote(@remarks) if remarks
181
180
  if siwl_weight
182
181
  builder.valSiwlWeight(siwl_weight.wgt.trim)
183
- builder.uomSiwlWeight(siwl_weight.unit.to_s.upcase)
182
+ builder.uomSiwlWeight(siwl_weight.unit.upcase)
184
183
  end
185
184
  if siwl_tire_pressure
186
185
  builder.valSiwlTirePressure(siwl_tire_pressure.pres.trim)
187
- builder.uomSiwlTirePressure(siwl_tire_pressure.unit.to_s.upcase)
186
+ builder.uomSiwlTirePressure(siwl_tire_pressure.unit.upcase)
188
187
  end
189
188
  if auw_weight
190
189
  builder.valAuwWeight(auw_weight.wgt.trim)
191
- builder.uomAuwWeight(auw_weight.unit.to_s.upcase)
190
+ builder.uomAuwWeight(auw_weight.unit.upcase)
192
191
  end
193
- builder.target!
194
192
  end
195
193
  end
196
194
  end
@@ -141,9 +141,8 @@ module AIXM
141
141
  @days = value
142
142
  end
143
143
 
144
- # @return [String] AIXM or OFMX markup
145
- def to_xml
146
- builder = Builder::XmlMarkup.new(indent: 2)
144
+ # @!visibility private
145
+ def add_to(builder)
147
146
  builder.Timsh do |timsh|
148
147
  timsh.codeTimeRef(adjust_to_dst? ? 'UTCW' : 'UTC')
149
148
  timsh.dateValidWef(dates.begin.to_s('%d-%m'))
@@ -151,23 +150,23 @@ module AIXM
151
150
  timsh.dateValidTil(dates.end.to_s('%d-%m'))
152
151
  timsh.dateYearValidTil(dates.end.year) if AIXM.ofmx? && !dates.end.yearless?
153
152
  if days.instance_of? Range
154
- timsh.codeDay(DAYS.key(days.begin.day).to_s)
155
- timsh.codeDayTil(DAYS.key(days.end.day).to_s)
153
+ timsh.codeDay(DAYS.key(days.begin.day))
154
+ timsh.codeDayTil(DAYS.key(days.end.day))
156
155
  else
157
- timsh.codeDay(DAYS.key(days.day).to_s)
156
+ timsh.codeDay(DAYS.key(days.day))
158
157
  end
159
158
  if times
160
159
  if times.begin
161
160
  timsh.timeWef(times.begin.to_s('%R'))
162
- timsh.codeEventWef(EVENTS.key(times.begin.event).to_s) if times.begin.event
161
+ timsh.codeEventWef(EVENTS.key(times.begin.event)) if times.begin.event
163
162
  timsh.timeRelEventWef(times.begin.delta) unless times.begin.delta.zero?
164
- timsh.codeCombWef(PRECEDENCES.key(times.begin.precedence).to_s) if times.begin.precedence
163
+ timsh.codeCombWef(PRECEDENCES.key(times.begin.precedence)) if times.begin.precedence
165
164
  end
166
165
  if times.end
167
166
  timsh.timeTil(times.end.to_s('%R'))
168
- timsh.codeEventTil(EVENTS.key(times.end.event).to_s) if times.end.event
167
+ timsh.codeEventTil(EVENTS.key(times.end.event)) if times.end.event
169
168
  timsh.timeRelEventTil(times.end.delta) unless times.end.delta.zero?
170
- timsh.codeCombTil(PRECEDENCES.key(times.end.precedence).to_s) if times.end.precedence
169
+ timsh.codeCombTil(PRECEDENCES.key(times.end.precedence)) if times.end.precedence
171
170
  end
172
171
  end
173
172
  end
@@ -18,7 +18,7 @@ module AIXM
18
18
  #
19
19
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Timetable#predefined-timetable
20
20
  class Timetable < Component
21
- include AIXM::Association
21
+ include AIXM::Concerns::Association
22
22
  include AIXM::Concerns::Remarks
23
23
 
24
24
  CODES = {
@@ -70,13 +70,12 @@ module AIXM
70
70
  end
71
71
  end
72
72
 
73
- # @return [String] AIXM or OFMX markup
74
- def to_xml(as: :Timetable)
75
- builder = Builder::XmlMarkup.new(indent: 2)
76
- builder.tag!(as) do |tag|
77
- tag.codeWorkHr(CODES.key(code).to_s)
73
+ # @!visibility private
74
+ def add_to(builder, as: :Timetable)
75
+ builder.send(as) do |tag|
76
+ tag.codeWorkHr(CODES.key(code))
78
77
  timesheets.each do |timesheet|
79
- tag << timesheet.to_xml.indent(2)
78
+ timesheet.add_to(tag)
80
79
  end
81
80
  tag.txtRmkWorkHr(remarks) if remarks
82
81
  end
@@ -116,19 +116,17 @@ module AIXM
116
116
  @meht = value
117
117
  end
118
118
 
119
- # @return [String] AIXM or OFMX markup
120
- def to_xml
121
- builder = Builder::XmlMarkup.new(indent: true)
122
- builder.codeTypeVasis(TYPES.key(type).to_s) if type
123
- builder.codePsnVasis(POSITIONS.key(position).to_s) if position
124
- builder.noBoxVasis(boxes.to_s) if boxes
119
+ # @!visibility private
120
+ def add_to(builder)
121
+ builder.codeTypeVasis(TYPES.key(type)) if type
122
+ builder.codePsnVasis(POSITIONS.key(position)) if position
123
+ builder.noBoxVasis(boxes) if boxes
125
124
  builder.codePortableVasis(portable ? 'Y' : 'N') unless portable.nil?
126
125
  builder.valSlopeAngleGpVasis(slope_angle.to_f) if slope_angle
127
126
  if meht
128
- builder.valMeht(meht.alt.to_s)
127
+ builder.valMeht(meht.alt)
129
128
  builder.uomMeht('FT')
130
129
  end
131
- builder.target!
132
130
  end
133
131
  end
134
132
  end
@@ -26,7 +26,7 @@ module AIXM
26
26
  #
27
27
  # @see https://gitlab.com/openflightmaps/ofmx/wikis/Airspace#ase-airspace
28
28
  class VerticalLimit < Component
29
- include AIXM::Association
29
+ include AIXM::Concerns::Association
30
30
 
31
31
  # @api private
32
32
  TAGS = { upper_z: :Upper, lower_z: :Lower, max_z: :Max, min_z: :Mnm }.freeze
@@ -102,15 +102,15 @@ module AIXM
102
102
  @min_z = value
103
103
  end
104
104
 
105
- # @return [String] AIXM or OFMX markup
106
- def to_xml
107
- TAGS.keys.each_with_object(Builder::XmlMarkup.new(indent: 2)) do |limit, builder|
105
+ # @!visibility private
106
+ def add_to(builder)
107
+ TAGS.each_key do |limit|
108
108
  if z = send(limit)
109
- builder.tag!(:"codeDistVer#{TAGS[limit]}", CODES[z.code].to_s)
110
- builder.tag!(:"valDistVer#{TAGS[limit]}", z.alt.to_s)
111
- builder.tag!(:"uomDistVer#{TAGS[limit]}", z.unit.upcase.to_s)
109
+ builder.send(:"codeDistVer#{TAGS[limit]}", CODES[z.code])
110
+ builder.send(:"valDistVer#{TAGS[limit]}", z.alt)
111
+ builder.send(:"uomDistVer#{TAGS[limit]}", z.unit.upcase)
112
112
  end
113
- end.target!
113
+ end
114
114
  end
115
115
  end
116
116
 
@@ -2,12 +2,13 @@ module AIXM
2
2
 
3
3
  # @abstract
4
4
  class Component
5
+ include AIXM::Concerns::XMLBuilder
5
6
  include AIXM::Concerns::HashEquality
6
7
 
7
- # Freely usable e.g. to +find_by+ foreign keys
8
+ # Freely usable e.g. to find_by foreign keys.
8
9
  #
9
10
  # @return [Object]
10
11
  attr_accessor :meta
11
-
12
12
  end
13
+
13
14
  end