aixm 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.ruby-version +1 -1
- data/.yardopts +3 -0
- data/CHANGELOG.md +34 -14
- data/Guardfile +1 -0
- data/README.md +64 -257
- data/lib/aixm.rb +16 -7
- data/lib/aixm/component.rb +6 -0
- data/lib/aixm/component/frequency.rb +135 -0
- data/lib/aixm/component/geometry.rb +34 -23
- data/lib/aixm/component/geometry/arc.rb +37 -22
- data/lib/aixm/component/geometry/border.rb +29 -20
- data/lib/aixm/component/geometry/circle.rb +39 -22
- data/lib/aixm/component/geometry/point.rb +29 -13
- data/lib/aixm/component/helipad.rb +154 -0
- data/lib/aixm/component/layer.rb +91 -0
- data/lib/aixm/component/runway.rb +294 -0
- data/lib/aixm/component/service.rb +170 -0
- data/lib/aixm/component/timetable.rb +65 -0
- data/lib/aixm/component/vertical_limits.rb +65 -29
- data/lib/aixm/config.rb +87 -0
- data/lib/aixm/document.rb +66 -42
- data/lib/aixm/errors.rb +11 -0
- data/lib/aixm/f.rb +34 -20
- data/lib/aixm/feature.rb +38 -0
- data/lib/aixm/feature/airport.rb +473 -0
- data/lib/aixm/feature/airspace.rb +145 -92
- data/lib/aixm/feature/navigational_aid.rb +94 -0
- data/lib/aixm/feature/navigational_aid/designated_point.rb +50 -54
- data/lib/aixm/feature/navigational_aid/dme.rb +48 -40
- data/lib/aixm/feature/navigational_aid/marker.rb +55 -45
- data/lib/aixm/feature/navigational_aid/ndb.rb +54 -50
- data/lib/aixm/feature/navigational_aid/tacan.rb +38 -31
- data/lib/aixm/feature/navigational_aid/vor.rb +84 -76
- data/lib/aixm/feature/organisation.rb +97 -0
- data/lib/aixm/feature/unit.rb +152 -0
- data/lib/aixm/refinements.rb +132 -47
- data/lib/aixm/shortcuts.rb +11 -6
- data/lib/aixm/version.rb +1 -1
- data/lib/aixm/xy.rb +64 -20
- data/lib/aixm/z.rb +51 -22
- data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-DataTypes.xsd +0 -0
- data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-Features.xsd +0 -0
- data/{lib/aixm/schemas → schemas/aixm}/4.5/AIXM-Snapshot.xsd +0 -0
- data/schemas/ofmx/0/OFMX-DataTypes.xsd +5077 -0
- data/schemas/ofmx/0/OFMX-Features.xsd +9955 -0
- data/schemas/ofmx/0/OFMX-Snapshot.xsd +217 -0
- data/spec/factory.rb +209 -33
- data/spec/lib/aixm/component/frequency_spec.rb +75 -0
- data/spec/lib/aixm/component/geometry/arc_spec.rb +28 -22
- data/spec/lib/aixm/component/geometry/border_spec.rb +23 -20
- data/spec/lib/aixm/component/geometry/circle_spec.rb +31 -22
- data/spec/lib/aixm/component/geometry/point_spec.rb +11 -14
- data/spec/lib/aixm/component/geometry_spec.rb +150 -69
- data/spec/lib/aixm/component/helipad_spec.rb +136 -0
- data/spec/lib/aixm/component/layer_spec.rb +110 -0
- data/spec/lib/aixm/component/runway_spec.rb +402 -0
- data/spec/lib/aixm/component/service_spec.rb +61 -0
- data/spec/lib/aixm/component/timetable_spec.rb +49 -0
- data/spec/lib/aixm/component/vertical_limits_spec.rb +39 -20
- data/spec/lib/aixm/config_spec.rb +41 -0
- data/spec/lib/aixm/document_spec.rb +637 -147
- data/spec/lib/aixm/errors_spec.rb +14 -0
- data/spec/lib/aixm/f_spec.rb +17 -10
- data/spec/lib/aixm/feature/airport_spec.rb +546 -0
- data/spec/lib/aixm/feature/airspace_spec.rb +349 -226
- data/spec/lib/aixm/feature/navigational_aid/designated_point_spec.rb +47 -36
- data/spec/lib/aixm/feature/navigational_aid/dme_spec.rb +61 -36
- data/spec/lib/aixm/feature/navigational_aid/marker_spec.rb +61 -113
- data/spec/lib/aixm/feature/navigational_aid/ndb_spec.rb +65 -79
- data/spec/lib/aixm/feature/navigational_aid/tacan_spec.rb +57 -36
- data/spec/lib/aixm/feature/navigational_aid/vor_spec.rb +86 -112
- data/spec/lib/aixm/feature/navigational_aid_spec.rb +52 -0
- data/spec/lib/aixm/feature/organisation_spec.rb +77 -0
- data/spec/lib/aixm/feature/unit_spec.rb +227 -0
- data/spec/lib/aixm/feature_spec.rb +58 -0
- data/spec/lib/aixm/refinements_spec.rb +187 -178
- data/spec/lib/aixm/xy_spec.rb +45 -34
- data/spec/lib/aixm/z_spec.rb +19 -21
- data/spec/macros/organisation.rb +11 -0
- data/spec/macros/remarks.rb +12 -0
- data/spec/macros/timetable.rb +11 -0
- data/spec/macros/xy.rb +11 -0
- data/spec/macros/z_qnh.rb +11 -0
- data/spec/spec_helper.rb +26 -0
- metadata +60 -19
- data/lib/aixm/base.rb +0 -10
- data/lib/aixm/component/base.rb +0 -6
- data/lib/aixm/component/class_layer.rb +0 -46
- data/lib/aixm/component/geometry/base.rb +0 -8
- data/lib/aixm/component/schedule.rb +0 -43
- data/lib/aixm/feature/base.rb +0 -6
- data/lib/aixm/feature/navigational_aid/base.rb +0 -79
- data/spec/lib/aixm/component/class_layer_spec.rb +0 -74
- data/spec/lib/aixm/component/schedule_spec.rb +0 -33
- data/spec/lib/aixm/feature/navigational_aid/base_spec.rb +0 -41
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
using AIXM::Refinements
|
|
2
|
+
|
|
3
|
+
module AIXM
|
|
4
|
+
class Component
|
|
5
|
+
|
|
6
|
+
# Service provided by a unit.
|
|
7
|
+
#
|
|
8
|
+
# ===Cheat Sheet in Pseudo Code:
|
|
9
|
+
# service = AIXM.service(
|
|
10
|
+
# name: String
|
|
11
|
+
# type: TYPES
|
|
12
|
+
# )
|
|
13
|
+
# service.timetable = AIXM.timetable or nil
|
|
14
|
+
# service.remarks = String or nil
|
|
15
|
+
# service.add_frequency(AIXM.frequency)
|
|
16
|
+
#
|
|
17
|
+
# @see https://github.com/openflightmaps/ofmx/wiki/Organisation#ser-service
|
|
18
|
+
class Service
|
|
19
|
+
TYPES = {
|
|
20
|
+
ACS: :area_control_service,
|
|
21
|
+
ADS: :automatic_dependent_surveillance_service,
|
|
22
|
+
ADVS: :advisory_service,
|
|
23
|
+
AFIS: :aerodrome_flight_information_service,
|
|
24
|
+
AFS: :aeronautical_fixed_service,
|
|
25
|
+
AIS: :aeronautical_information_service,
|
|
26
|
+
ALRS: :alerting_service,
|
|
27
|
+
AMS: :aeronautical_mobile_service,
|
|
28
|
+
AMSS: :aeronautical_mobile_satellite_service,
|
|
29
|
+
APP: :approach_control_service,
|
|
30
|
+
'APP-ARR': :approach_control_service_for_arrival,
|
|
31
|
+
'APP-DEP': :approach_control_service_for_departure,
|
|
32
|
+
ARTCC: :air_route_traffic_control_centre_service,
|
|
33
|
+
ATC: :air_traffic_control_service,
|
|
34
|
+
ATFM: :air_traffic_flow_management_service,
|
|
35
|
+
ATIS: :automated_terminal_information_service,
|
|
36
|
+
'ATIS-ARR': :automated_terminal_information_service_for_arrival,
|
|
37
|
+
'ATIS-DEP': :automated_terminal_information_service_for_departure,
|
|
38
|
+
ATM: :air_traffic_management_service,
|
|
39
|
+
ATS: :air_traffic_service,
|
|
40
|
+
BOF: :briefing_service,
|
|
41
|
+
BS: :commercial_broadcasting_service,
|
|
42
|
+
COM: :communications_service,
|
|
43
|
+
CTAF: :common_traffic_advisory_frequency_service,
|
|
44
|
+
DVDF: :doppler_vdf_service,
|
|
45
|
+
EFAS: :en_route_flight_advisory_service,
|
|
46
|
+
ENTRY: :entry_clearance_service,
|
|
47
|
+
EXIT: :exit_clearance_service,
|
|
48
|
+
FCST: :forecasting_service,
|
|
49
|
+
FIS: :flight_information_service,
|
|
50
|
+
FISA: :automated_flight_information_service,
|
|
51
|
+
FSS: :flight_service_station_service,
|
|
52
|
+
GCA: :ground_controlled_approach_service,
|
|
53
|
+
INFO: :information_provision_service,
|
|
54
|
+
MET: :meteorological_service,
|
|
55
|
+
NOF: :international_notam_service,
|
|
56
|
+
OAC: :oceanic_area_control_service,
|
|
57
|
+
OVERFLT: :overflight_clearance_service,
|
|
58
|
+
PAR: :precision_approach_radar_service,
|
|
59
|
+
RAC: :rules_of_the_air_and_air_traffic_services,
|
|
60
|
+
RADAR: :radar_service,
|
|
61
|
+
RAF: :regional_area_forecasting_service,
|
|
62
|
+
RCC: :rescue_coordination_service,
|
|
63
|
+
SAR: :search_and_rescue_service,
|
|
64
|
+
SIGMET: :sigmet_service,
|
|
65
|
+
SMC: :surface_movement_control_service,
|
|
66
|
+
SMR: :surface_movement_radar_service,
|
|
67
|
+
SRA: :surveillance_radar_approach_service,
|
|
68
|
+
SSR: :secondary_surveillance_radar_service,
|
|
69
|
+
TAR: :terminal_area_radar_service,
|
|
70
|
+
TWEB: :transcribed_weather_broadcast_service,
|
|
71
|
+
TWR: :aerodrome_control_tower_service,
|
|
72
|
+
UAC: :upper_area_control_service,
|
|
73
|
+
UDF: :uhf_direction_finding_service,
|
|
74
|
+
VDF: :vhf_direction_finding_service,
|
|
75
|
+
VOLMET: :volmet_service,
|
|
76
|
+
VOT: :vor_test_facility,
|
|
77
|
+
OTHER: :other # specify in remarks
|
|
78
|
+
}.freeze
|
|
79
|
+
|
|
80
|
+
# @return [AIXM::Feature::Unit] unit providing this service
|
|
81
|
+
attr_reader :unit
|
|
82
|
+
|
|
83
|
+
# @return [String] full name
|
|
84
|
+
attr_reader :name
|
|
85
|
+
|
|
86
|
+
# @return [Symbol] type of service (see {TYPES})
|
|
87
|
+
attr_reader :type
|
|
88
|
+
|
|
89
|
+
# @return [AIXM::Component::Timetable, nil] operating hours
|
|
90
|
+
attr_reader :timetable
|
|
91
|
+
|
|
92
|
+
# @return [String, nil] free text remarks
|
|
93
|
+
attr_reader :remarks
|
|
94
|
+
|
|
95
|
+
# @return [Array<AIXM::Component::Frequency>] frequencies used by this service
|
|
96
|
+
attr_reader :frequencies
|
|
97
|
+
|
|
98
|
+
def initialize(name:, type:)
|
|
99
|
+
self.name, self.type = name, type
|
|
100
|
+
@frequencies = []
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @return [String]
|
|
104
|
+
def inspect
|
|
105
|
+
%Q(#<#{self.class} type=#{type.inspect}>)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def unit=(value)
|
|
109
|
+
fail(ArgumentError, "invalid unit") unless value.is_a? AIXM::Feature::Unit
|
|
110
|
+
@unit = value
|
|
111
|
+
end
|
|
112
|
+
private :unit=
|
|
113
|
+
|
|
114
|
+
def name=(value)
|
|
115
|
+
fail(ArgumentError, "invalid name") unless value.is_a? String
|
|
116
|
+
@name = value.uptrans
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def type=(value)
|
|
120
|
+
@type = TYPES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid type")
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def timetable=(value)
|
|
124
|
+
fail(ArgumentError, "invalid timetable") unless value.nil? || value.is_a?(AIXM::Component::Timetable)
|
|
125
|
+
@timetable = value
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def remarks=(value)
|
|
129
|
+
@remarks = value&.to_s
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Add a frequency used by this service.
|
|
133
|
+
#
|
|
134
|
+
# @param frequency [AIXM::Component::Frequency] frequency instance
|
|
135
|
+
# @return [self]
|
|
136
|
+
def add_frequency(frequency)
|
|
137
|
+
fail(ArgumentError, "invalid frequency") unless frequency.is_a? AIXM::Component::Frequency
|
|
138
|
+
frequency.send(:service=, self)
|
|
139
|
+
@frequencies << frequency
|
|
140
|
+
self
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# @return [String] UID markup
|
|
144
|
+
def to_uid
|
|
145
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
|
146
|
+
builder.SerUid do |ser_uid|
|
|
147
|
+
ser_uid << unit.to_uid.indent(2)
|
|
148
|
+
ser_uid.codeType(TYPES.key(type).to_s)
|
|
149
|
+
ser_uid.noSeq(@sequence)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# @return [String] AIXM or OFMX markup
|
|
154
|
+
def to_xml(sequence=1)
|
|
155
|
+
@sequence = sequence
|
|
156
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
|
157
|
+
builder.Ser do |ser|
|
|
158
|
+
ser << to_uid.indent(2)
|
|
159
|
+
ser << timetable.to_xml(as: :Stt).indent(2) if timetable
|
|
160
|
+
ser.txtRmk(remarks) if remarks
|
|
161
|
+
end
|
|
162
|
+
frequencies.each do |frequency|
|
|
163
|
+
builder << frequency.to_xml
|
|
164
|
+
end
|
|
165
|
+
builder.target!
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
using AIXM::Refinements
|
|
2
|
+
|
|
3
|
+
module AIXM
|
|
4
|
+
class Component
|
|
5
|
+
|
|
6
|
+
# Timetables define activity time windows.
|
|
7
|
+
#
|
|
8
|
+
# @note As of now, only predefined timetables (see {CODES}) are imlemented.
|
|
9
|
+
#
|
|
10
|
+
# ===Cheat Sheat in Pseudo Code:
|
|
11
|
+
# timetable = AIXM.timetable(
|
|
12
|
+
# code: String or Symbol
|
|
13
|
+
# )
|
|
14
|
+
# timetable.remarks = String or nil
|
|
15
|
+
#
|
|
16
|
+
# ===Shortcuts:
|
|
17
|
+
# * +AIXM::H24+ - continuous, all day and all night
|
|
18
|
+
#
|
|
19
|
+
# @see https://github.com/openflightmaps/ofmx/wiki/Timetable#predefined-timetable
|
|
20
|
+
class Timetable
|
|
21
|
+
CODES = {
|
|
22
|
+
H24: :continuous, # all day and all night
|
|
23
|
+
HJ: :sunrise_to_sunset, # all day
|
|
24
|
+
HN: :sunset_to_sunrise, # all night
|
|
25
|
+
HX: :unspecified,
|
|
26
|
+
HO: :operational_request, # on request only
|
|
27
|
+
NOTAM: :notam, # see NOTAM
|
|
28
|
+
OTHER: :other # specify in remarks
|
|
29
|
+
}.freeze
|
|
30
|
+
|
|
31
|
+
# @return [Symbol] predefined timetable code (see {CODES})
|
|
32
|
+
attr_reader :code
|
|
33
|
+
|
|
34
|
+
# @return [String, nil] free text remarks
|
|
35
|
+
attr_reader :remarks
|
|
36
|
+
|
|
37
|
+
def initialize(code:)
|
|
38
|
+
self.code = code
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# @return [String]
|
|
42
|
+
def inspect
|
|
43
|
+
%Q(#<#{self.class} code=#{code.inspect}>)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def code=(value)
|
|
47
|
+
@code = CODES.lookup(value&.to_s&.to_sym, nil) || fail(ArgumentError, "invalid code")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def remarks=(value)
|
|
51
|
+
@remarks = value&.to_s
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [String] AIXM or OFMX markup
|
|
55
|
+
def to_xml(as: :Timetable)
|
|
56
|
+
builder = Builder::XmlMarkup.new(indent: 2)
|
|
57
|
+
builder.tag!(as) do |tag|
|
|
58
|
+
tag.codeWorkHr(CODES.key(code).to_s)
|
|
59
|
+
tag.txtRmkWorkHr(remarks) if remarks
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -1,49 +1,85 @@
|
|
|
1
|
+
using AIXM::Refinements
|
|
2
|
+
|
|
1
3
|
module AIXM
|
|
2
|
-
|
|
4
|
+
class Component
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
#
|
|
6
|
-
# as follows:
|
|
6
|
+
# Vertical limits define a 3D airspace vertically. They are often noted in
|
|
7
|
+
# AIP as follows:
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# upper_z (or max_z whichever is higher)
|
|
10
|
+
# -------
|
|
11
|
+
# lower_z (or min_z whichever is lower)
|
|
11
12
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
# ===Cheat Sheet in Pseudo Code:
|
|
14
|
+
# vertical_limits = AIXM.vertical_limits(
|
|
15
|
+
# upper_z: AIXM.z
|
|
16
|
+
# lower_z: AIXM.z
|
|
17
|
+
# max_z: AIXM.z or nil
|
|
18
|
+
# min_z: AIXM.z or nil
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# ===Shortcuts:
|
|
22
|
+
# * +AIXM::GROUND+ - surface expressed as "0 ft QFE"
|
|
23
|
+
# * +AIXM::UNLIMITED+ - no upper limit expressed as "FL 999"
|
|
24
|
+
#
|
|
25
|
+
# @see https://github.com/openflightmaps/ofmx/wiki/Airspace#ase-airspace
|
|
26
|
+
class VerticalLimits
|
|
27
|
+
# @api private
|
|
18
28
|
TAGS = { upper: :Upper, lower: :Lower, max: :Max, min: :Mnm }.freeze
|
|
29
|
+
|
|
30
|
+
# @api private
|
|
19
31
|
CODES = { qfe: :HEI, qnh: :ALT, qne: :STD }.freeze
|
|
20
32
|
|
|
21
|
-
|
|
33
|
+
# @return [AIXM::Z] upper limit
|
|
34
|
+
attr_reader :upper_z
|
|
35
|
+
|
|
36
|
+
# @return [AIXM::Z] lower limit
|
|
37
|
+
attr_reader :lower_z
|
|
38
|
+
|
|
39
|
+
# @return [AIXM::Z] alternative upper limit ("whichever is higher")
|
|
40
|
+
attr_reader :max_z
|
|
41
|
+
|
|
42
|
+
# @return [AIXM::Z] alternative lower limit ("whichever is lower")
|
|
43
|
+
attr_reader :min_z
|
|
44
|
+
|
|
45
|
+
def initialize(upper_z:, lower_z:, max_z: nil, min_z: nil)
|
|
46
|
+
self.upper_z, self.lower_z, self.max_z, self.min_z = upper_z, lower_z, max_z, min_z
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# @return [String]
|
|
50
|
+
def inspect
|
|
51
|
+
%Q(#<#{self.class} upper_z="#{upper_z.to_s}" lower_z="#{lower_z.to_s}">)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def upper_z=(value)
|
|
55
|
+
fail(ArgumentError, "invalid upper_z") unless value.is_a? AIXM::Z
|
|
56
|
+
@upper_z = value
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def lower_z=(value)
|
|
60
|
+
fail(ArgumentError, "invalid lower_z") unless value.is_a? AIXM::Z
|
|
61
|
+
@lower_z = value
|
|
62
|
+
end
|
|
22
63
|
|
|
23
|
-
def
|
|
24
|
-
fail(ArgumentError, "invalid
|
|
25
|
-
|
|
26
|
-
fail(ArgumentError, "invalid max_z") unless max_z.nil? || max_z.is_a?(AIXM::Z)
|
|
27
|
-
fail(ArgumentError, "invalid min_z") unless min_z.nil? || min_z.is_a?(AIXM::Z)
|
|
28
|
-
@upper_z, @lower_z, @max_z, @min_z = upper_z, lower_z, max_z, min_z
|
|
64
|
+
def max_z=(value)
|
|
65
|
+
fail(ArgumentError, "invalid max_z") unless value.nil? || value.is_a?(AIXM::Z)
|
|
66
|
+
@max_z = value
|
|
29
67
|
end
|
|
30
68
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
[upper_z.alt, upper_z.code, lower_z.alt, lower_z.code, max_z&.alt, max_z&.code, min_z&.alt, min_z&.code].to_digest
|
|
69
|
+
def min_z=(value)
|
|
70
|
+
fail(ArgumentError, "invalid min_z") unless value.nil? || value.is_a?(AIXM::Z)
|
|
71
|
+
@min_z = value
|
|
35
72
|
end
|
|
36
73
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def to_aixm(*extensions)
|
|
74
|
+
# @return [String] AIXM or OFMX markup
|
|
75
|
+
def to_xml
|
|
40
76
|
%i(upper lower max min).each_with_object(Builder::XmlMarkup.new(indent: 2)) do |limit, builder|
|
|
41
77
|
if z = send(:"#{limit}_z")
|
|
42
78
|
builder.tag!(:"codeDistVer#{TAGS[limit]}", CODES[z.code].to_s)
|
|
43
79
|
builder.tag!(:"valDistVer#{TAGS[limit]}", z.alt.to_s)
|
|
44
|
-
builder.tag!(:"uomDistVer#{TAGS[limit]}", z.unit.to_s)
|
|
80
|
+
builder.tag!(:"uomDistVer#{TAGS[limit]}", z.unit.upcase.to_s)
|
|
45
81
|
end
|
|
46
|
-
end.target!
|
|
82
|
+
end.target!
|
|
47
83
|
end
|
|
48
84
|
end
|
|
49
85
|
|
data/lib/aixm/config.rb
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module AIXM
|
|
2
|
+
|
|
3
|
+
SCHEMAS = {
|
|
4
|
+
aixm: {
|
|
5
|
+
version: '4.5',
|
|
6
|
+
namespace: 'http://www.aixm.aero/schema/4.5/AIXM-Snapshot.xsd',
|
|
7
|
+
xsd: Pathname(__dir__).join('..', '..', 'schemas', 'aixm', '4.5', 'AIXM-Snapshot.xsd'),
|
|
8
|
+
root: 'AIXM-Snapshot'
|
|
9
|
+
},
|
|
10
|
+
ofmx: {
|
|
11
|
+
version: '0',
|
|
12
|
+
namespace: 'http://openflightmaps.org/schema/0/OFMX-Snapshot.xsd',
|
|
13
|
+
xsd: Pathname(__dir__).join('..', '..', 'schemas', 'ofmx', '0', 'OFMX-Snapshot.xsd'),
|
|
14
|
+
root: 'OFMX-Snapshot'
|
|
15
|
+
}
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
18
|
+
class << self
|
|
19
|
+
|
|
20
|
+
# Access the configuration (e.g. +AIXM.config.schema+)
|
|
21
|
+
# @return [OpenStruct] configuration struct
|
|
22
|
+
def config
|
|
23
|
+
@@config
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Currently active schema
|
|
27
|
+
#
|
|
28
|
+
# @example Get the schema identifyer
|
|
29
|
+
# AIXM.schema # => :aixm
|
|
30
|
+
#
|
|
31
|
+
# @example Get schema details
|
|
32
|
+
# AIXM.schema(:version) # => '4.5'
|
|
33
|
+
# AIXM.schema(:root) # => 'AIXM-Snapshot'
|
|
34
|
+
#
|
|
35
|
+
# @param key [Symbol, nil] schema detail key (see {SCHEMAS})
|
|
36
|
+
# @return [Object] schema detail value
|
|
37
|
+
def schema(key = nil)
|
|
38
|
+
key ? SCHEMAS.dig(@@config.schema, key) : @@config.schema
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Shortcuts to set the schema.
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# AIXM.aixm! # => :aixm
|
|
45
|
+
# AIXM.ofmx? # => false
|
|
46
|
+
# AIXM.ofmx! # => :ofmx
|
|
47
|
+
# AIXM.ofmx? # => true
|
|
48
|
+
#
|
|
49
|
+
# @!method aixm!
|
|
50
|
+
# @!method ofmx!
|
|
51
|
+
# @return [Symbol] schema key
|
|
52
|
+
SCHEMAS.each_key do |schema|
|
|
53
|
+
define_method("#{schema}!") { @@config.schema = schema }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Shortcuts to query the schema.
|
|
57
|
+
#
|
|
58
|
+
# @example
|
|
59
|
+
# AIXM.aixm! # => :aixm
|
|
60
|
+
# AIXM.ofmx? # => false
|
|
61
|
+
# AIXM.ofmx! # => :ofmx
|
|
62
|
+
# AIXM.ofmx? # => true
|
|
63
|
+
#
|
|
64
|
+
# @!method aixm?
|
|
65
|
+
# @!method ofmx?
|
|
66
|
+
# @return [Boolean]
|
|
67
|
+
SCHEMAS.each_key do |schema|
|
|
68
|
+
define_method("#{schema}?") { @@config.schema == schema }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# Configuration defaults (view source for more).
|
|
74
|
+
#
|
|
75
|
+
# @!visibility public
|
|
76
|
+
# @api private
|
|
77
|
+
# @return [OpenStruct]
|
|
78
|
+
def initialize_config
|
|
79
|
+
@@config = OpenStruct.new(
|
|
80
|
+
schema: :aixm
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
AIXM.send(:initialize_config)
|
data/lib/aixm/document.rb
CHANGED
|
@@ -1,63 +1,89 @@
|
|
|
1
|
+
using AIXM::Refinements
|
|
2
|
+
|
|
1
3
|
module AIXM
|
|
2
|
-
class Document < Base
|
|
3
|
-
using AIXM::Refinements
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# The AIXM-Snapshot or OFMX-Snapshot document is the root container for
|
|
6
|
+
# aeronautical information such as airports or airspaces.
|
|
7
|
+
#
|
|
8
|
+
# ===Cheat Sheet in Pseudo Code:
|
|
9
|
+
# document = AIXM.document(
|
|
10
|
+
# namespace: String (UUID)
|
|
11
|
+
# created_at: Time or Date or String
|
|
12
|
+
# effective_at: Time or Date or String
|
|
13
|
+
# )
|
|
14
|
+
# document.features << AIXM::Feature
|
|
15
|
+
#
|
|
16
|
+
# @see https://github.com/openflightmaps/ofmx/wiki/Snapshot
|
|
17
|
+
class Document
|
|
18
|
+
NAMESPACE_PATTERN = /\A[a-f\d]{8}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{4}-[a-f\d]{12}\z/.freeze
|
|
19
|
+
|
|
20
|
+
# @return [String] UUID to namespace the data contained in this document
|
|
21
|
+
attr_reader :namespace
|
|
22
|
+
|
|
23
|
+
# @return [Time] creation date and time (default: {#effective_at} or now)
|
|
24
|
+
attr_reader :created_at
|
|
25
|
+
|
|
26
|
+
# @return [Time] effective after date and time (default: {#created_at} or now)
|
|
27
|
+
attr_reader :effective_at
|
|
6
28
|
|
|
7
|
-
|
|
29
|
+
# @return [Array<AIXM::Feature>] airspaces, airports and other features
|
|
8
30
|
attr_accessor :features
|
|
9
31
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
#
|
|
13
|
-
# Options:
|
|
14
|
-
# * +created_at+ - creation date and time (default: now)
|
|
15
|
-
# * +effective_at+ - snapshot effective after date and time (default: now)
|
|
16
|
-
def initialize(created_at: nil, effective_at: nil)
|
|
17
|
-
@created_at, @effective_at = parse_time(created_at), parse_time(effective_at)
|
|
32
|
+
def initialize(namespace: nil, created_at: nil, effective_at: nil)
|
|
33
|
+
self.namespace, self.created_at, self.effective_at = namespace, created_at, effective_at
|
|
18
34
|
@features = []
|
|
19
35
|
end
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
37
|
+
# @return [String]
|
|
38
|
+
def inspect
|
|
39
|
+
%Q(#<#{self.class} created_at=#{created_at.inspect}>)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def namespace=(value)
|
|
43
|
+
fail(ArgumentError, "invalid namespace") unless value.nil? || value.match?(NAMESPACE_PATTERN)
|
|
44
|
+
@namespace = value || SecureRandom.uuid
|
|
25
45
|
end
|
|
26
46
|
|
|
27
|
-
|
|
28
|
-
|
|
47
|
+
def created_at=(value)
|
|
48
|
+
@created_at = parse_time(value) || effective_at || Time.now
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def effective_at=(value)
|
|
52
|
+
@effective_at = parse_time(value) || created_at || Time.now
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Validate the generated AIXM or OFMX atainst it's XSD.
|
|
56
|
+
#
|
|
57
|
+
# @return [Boolean] whether valid or not
|
|
29
58
|
def valid?
|
|
30
59
|
errors.none?
|
|
31
60
|
end
|
|
32
61
|
|
|
33
|
-
|
|
34
|
-
#
|
|
62
|
+
# Validate the generated AIXM or OFMX atainst it's XSD and return the
|
|
63
|
+
# errors found.
|
|
64
|
+
#
|
|
65
|
+
# @return [Array<String>] validation errors
|
|
35
66
|
def errors
|
|
36
|
-
xsd = Nokogiri::XML::Schema(File.open(AIXM
|
|
37
|
-
xsd.validate(Nokogiri::XML(
|
|
38
|
-
error.message
|
|
67
|
+
xsd = Nokogiri::XML::Schema(File.open(AIXM.schema(:xsd)))
|
|
68
|
+
xsd.validate(Nokogiri::XML(to_xml)).reject do |error|
|
|
69
|
+
AIXM.config.ignored_errors && error.message.match?(AIXM.config.ignored_errors)
|
|
39
70
|
end
|
|
40
71
|
end
|
|
41
72
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
# Extensions:
|
|
46
|
-
# * +:ofm+ - Open Flightmaps
|
|
47
|
-
def to_aixm(*extensions)
|
|
48
|
-
now = Time.now.xmlschema
|
|
73
|
+
# @return [String] AIXM or OFMX markup
|
|
74
|
+
def to_xml
|
|
49
75
|
meta = {
|
|
50
|
-
'xmlns:xsi':
|
|
51
|
-
version:
|
|
52
|
-
origin: "
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
76
|
+
'xmlns:xsi': AIXM.schema(:namespace),
|
|
77
|
+
version: AIXM.schema(:version),
|
|
78
|
+
origin: "rubygem aixm-#{AIXM::VERSION}",
|
|
79
|
+
namespace: (namespace if AIXM.ofmx?),
|
|
80
|
+
created: @created_at.xmlschema,
|
|
81
|
+
effective: @effective_at.xmlschema
|
|
82
|
+
}.compact
|
|
57
83
|
builder = Builder::XmlMarkup.new(indent: 2)
|
|
58
84
|
builder.instruct!
|
|
59
|
-
builder.tag!(
|
|
60
|
-
|
|
85
|
+
builder.tag!(AIXM.schema(:root), meta) do |root|
|
|
86
|
+
root << features.map { |f| f.to_xml }.join.indent(2)
|
|
61
87
|
end
|
|
62
88
|
end
|
|
63
89
|
|
|
@@ -69,10 +95,8 @@ module AIXM
|
|
|
69
95
|
when Date then value.to_time
|
|
70
96
|
when Time then value
|
|
71
97
|
when nil then nil
|
|
72
|
-
else fail
|
|
98
|
+
else fail(ArgumentError, "invalid date or time")
|
|
73
99
|
end
|
|
74
|
-
rescue ArgumentError
|
|
75
|
-
raise(ArgumentError, "`#{value}' is not a valid date and time")
|
|
76
100
|
end
|
|
77
101
|
|
|
78
102
|
end
|