aipp 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +26 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +9 -0
- data/README.md +59 -7
- data/aipp.gemspec +3 -2
- data/lib/aipp.rb +2 -0
- data/lib/aipp/aip.rb +4 -12
- data/lib/aipp/downloader.rb +21 -21
- data/lib/aipp/executable.rb +4 -1
- data/lib/aipp/parser.rb +58 -5
- data/lib/aipp/regions/LF/AD-1.3.rb +27 -13
- data/lib/aipp/regions/LF/AD-1.6.rb +2 -2
- data/lib/aipp/regions/LF/AD-2.rb +30 -6
- data/lib/aipp/regions/LF/AD-3.1.rb +2 -2
- data/lib/aipp/regions/LF/ENR-2.1.rb +1 -1
- data/lib/aipp/regions/LF/ENR-4.1.rb +20 -78
- data/lib/aipp/regions/LF/ENR-4.3.rb +1 -1
- data/lib/aipp/regions/LF/ENR-5.1.rb +44 -26
- data/lib/aipp/regions/LF/ENR-5.5.rb +1 -1
- data/lib/aipp/regions/LF/helpers/{common.rb → base.rb} +2 -2
- data/lib/aipp/regions/LF/helpers/navigational_aid.rb +104 -0
- data/lib/aipp/regions/LF/helpers/{AD_radio.rb → radio_AD.rb} +24 -12
- data/lib/aipp/version.rb +1 -1
- data/lib/core_ext/object.rb +1 -1
- data/spec/fixtures/{archive.zip → source.zip} +0 -0
- data/spec/lib/aipp/airac_spec.rb +18 -18
- data/spec/lib/aipp/border_spec.rb +19 -19
- data/spec/lib/aipp/downloader_spec.rb +25 -25
- data/spec/lib/aipp/patcher_spec.rb +4 -4
- data/spec/lib/aipp/pdf_spec.rb +23 -23
- data/spec/lib/aipp/t_hash_spec.rb +6 -6
- data/spec/lib/aipp/version_spec.rb +1 -1
- data/spec/lib/core_ext/enumberable_spec.rb +15 -15
- data/spec/lib/core_ext/hash_spec.rb +4 -4
- data/spec/lib/core_ext/integer_spec.rb +2 -2
- data/spec/lib/core_ext/nil_class_spec.rb +1 -1
- data/spec/lib/core_ext/string_spec.rb +28 -28
- data/spec/spec_helper.rb +1 -0
- metadata +27 -12
- data/.travis.yml +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cddca26d9635de7aa2ded8bde0def36adf97d548e9c133358443f7812c778ef6
|
4
|
+
data.tar.gz: cadd71e6709c70f03a6f2ceda4af1ef38b049d70f3aaad2cd45ef3fc792df192
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d511918c12c5c877c64cb4d5f28e5d968cdd98e08f9dfc72b8f188579da214aa63e953b36a5f17dbdd8b2d5d0281209f29d2693a458c4b7613d0d012c4111e7
|
7
|
+
data.tar.gz: b3b4a1dc343049c3aec1c58290e52d09fb43adb476a6c085271d31f0d20c016db19cb9ed0f4355e8eb78f199fa3e6b9580a2f2a30d2e6ff8bcc6548f818d8e08
|
@@ -0,0 +1,26 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby:
|
15
|
+
- 2.6.x
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v1
|
18
|
+
- name: Set up Ruby ${{ matrix.ruby }}
|
19
|
+
uses: actions/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby }}
|
22
|
+
- name: Build and test
|
23
|
+
run: |
|
24
|
+
gem install bundler
|
25
|
+
bundle install --jobs 4 --retry 3
|
26
|
+
bundle exec rake
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.6.
|
1
|
+
ruby-2.6.5
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
## 0.2.5
|
2
|
+
|
3
|
+
#### Additions
|
4
|
+
* LF/AD-2>2.19 (AD navigational aids relevant to VFR)
|
5
|
+
* Write build and manifest to `~/.aipp/<region>/builds`
|
6
|
+
|
7
|
+
#### Changes
|
8
|
+
* Renamed `~/.aipp/<region>/archive` to `~/.aipp/<region>/sources`
|
9
|
+
|
1
10
|
## 0.2.4
|
2
11
|
|
3
12
|
#### Additions
|
data/README.md
CHANGED
@@ -1,20 +1,31 @@
|
|
1
1
|
[![Version](https://img.shields.io/gem/v/aipp.svg?style=flat)](https://rubygems.org/gems/aipp)
|
2
|
-
[![
|
2
|
+
[![Tests](https://github.com/svoop/aipp/workflows/Test/badge.svg)](https://github.com/svoop/aipp/actions?workflow=Test)
|
3
3
|
[![Donorbox](https://img.shields.io/badge/donate-on_donorbox-yellow.svg)](https://donorbox.org/bitcetera)
|
4
4
|
|
5
5
|
# AIPP
|
6
6
|
|
7
7
|
Parser for Aeronautical Information Publication (AIP) available online.
|
8
8
|
|
9
|
-
This gem incluces two executables to download and parse aeronautical data as HTML or PDF, then export is as [AIXM](https://github.com/svoop/aixm) or [OFMX](https://github.com/openflightmaps/ofmx/wiki).
|
9
|
+
This gem incluces two executables to download and parse aeronautical data as HTML or PDF, then build and export is as [AIXM](https://github.com/svoop/aixm) or [OFMX](https://github.com/openflightmaps/ofmx/wiki).
|
10
10
|
|
11
11
|
* [Homepage](https://github.com/svoop/aipp)
|
12
12
|
* [Rubydoc](https://www.rubydoc.info/gems/aipp/AIPP)
|
13
13
|
* Author: [Sven Schwyn - Bitcetera](http://www.bitcetera.com)
|
14
14
|
|
15
|
+
## Table of Contents
|
16
|
+
|
17
|
+
[Install](#install)<br>
|
18
|
+
[Usage](#usage)<br>
|
19
|
+
[Storage](#storage)<br>
|
20
|
+
[Regions](#regions)<br>
|
21
|
+
[AIP Parsers](#aip-parsers)<br>
|
22
|
+
[References](#references)<br>
|
23
|
+
[AIRAC Date Calculations](#airac-date-calculations)<br>
|
24
|
+
[Development](#development)
|
25
|
+
|
15
26
|
## Install
|
16
27
|
|
17
|
-
Add this to your <tt>Gemfile</tt>:
|
28
|
+
Add this to your <tt>Gemfile</tt> or <tt>gems.rb</tt>:
|
18
29
|
|
19
30
|
```ruby
|
20
31
|
gem aipp
|
@@ -22,15 +33,56 @@ gem aipp
|
|
22
33
|
|
23
34
|
## Usage
|
24
35
|
|
36
|
+
See the built-in help for all options:
|
37
|
+
|
25
38
|
```
|
26
39
|
aip2aixm --help
|
27
40
|
aip2ofmx --help
|
28
41
|
```
|
29
42
|
|
43
|
+
Say, you with to build the complete OFMX file for the current AIRAC cycle of the region LF:
|
44
|
+
|
45
|
+
```
|
46
|
+
aip2ofmx -r LF
|
47
|
+
```
|
48
|
+
|
49
|
+
You'll find the OFMX file in the current directory if the binary exits successfully.
|
50
|
+
|
30
51
|
## Storage
|
31
52
|
|
32
53
|
AIPP uses a storage directory for configuration, caching and in order to keep the results of previous runs. The default location is `~/.aipp`, however, you can pass a different directory with the `--storage` argument.
|
33
54
|
|
55
|
+
You'll find a directory for each region which contains the following items:
|
56
|
+
|
57
|
+
* `sources/`<br>This directory contains one ZIP archive per AIRAC cycle which incrementially caches all source files used to build the AIXM/OFMX file. Therefore, to make sure it contains all source files for a region, you have to build at least one complete AIXM/OFMX file for that region.
|
58
|
+
* `builds/`<br>This directory contains one ZIP archive per AIRAC cycle which is overwritten on every run. Therefore, to make sure it contains the complete build for a region, you have to make sure that your last run builds the complete AIXM/OFMX for that region. This archive contains:
|
59
|
+
* the built AIXM/OFMX file
|
60
|
+
* `build.yaml` – context of the build process
|
61
|
+
* `manifest.csv` – diffable manifest (see below)
|
62
|
+
* `config.yml`<br>This file contains configuration which will be read on subsequent runs, most notably the namespace UUID used to identify the creator of OFMX files.
|
63
|
+
|
64
|
+
The manifest is a CSV which lists every feature on a separate line along with its hashes and comment. You can `diff` or `git diff` two manifests:
|
65
|
+
|
66
|
+
```diff
|
67
|
+
$ git diff -U0 2019-09-12/manifest.csv 2019-10-10/manifest.csv
|
68
|
+
|
69
|
+
--- a/2019-09-12/manifest.csv
|
70
|
+
+++ b/2019-10-10/manifest.csv
|
71
|
+
@@ -89,0 +90 @@ Aha,449f4791,d6d4bff8,Address: PHONE for LFF958FC61
|
72
|
+
+Aha,44b9a044,cf55a3cf,Address: PHONE for LF49929DD6
|
73
|
+
@@ -134 +135 @@ Aha,6acfbcc5,c4f57e3f,Address: FAX for LF897E1A6F
|
74
|
+
-Aha,6b381b32,fb947716,Address: RADIO for LFPO
|
75
|
+
+Aha,6b381b32,b9723b7e,Address: RADIO for LFPO
|
76
|
+
@@ -253,0 +255 @@ Aha,d01c4282,7cc8db7f,Address: PHONE for LF0C413AE2
|
77
|
+
+Aha,d05cfbff,74fb76bc,Address: FAX for LF49929DD6
|
78
|
+
@@ -327 +329 @@ Ahp,068f4f01,1dc2fb5c,Airport: LFEA BELLE ILE
|
79
|
+
-Ahp,06d04910,e18af958,Airport: LFFDE9077D TONNERRE CENTRE HOSPITALIER
|
80
|
+
+Ahp,06d04910,cc522711,Airport: LFFDE9077D TONNERRE CENTRE HOSPITALIER
|
81
|
+
(...)
|
82
|
+
```
|
83
|
+
|
84
|
+
The advantage of `git diff` is it's ability to hightlight exactly which part of a line has changed. [Check out this post to learn how](https://www.viget.com/articles/dress-up-your-git-diffs-with-word-level-highlights/).
|
85
|
+
|
34
86
|
## Regions
|
35
87
|
|
36
88
|
The reference implementation is region "LF" (France).
|
@@ -83,7 +135,7 @@ Inside the `parse` method, you have access to the following methods:
|
|
83
135
|
|
84
136
|
* [`read`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#read-instance_method) – download and read an AIP file
|
85
137
|
* [`add`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#add-instance_method) – add a [`AIXM::Feature`](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
|
86
|
-
* [`select`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find-instance_method – search previously written [`AIXM::Feature`s](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
|
138
|
+
* [`select`](https://www.rubydoc.info/gems/aipp/AIPP/AIP#find-instance_method) – search previously written [`AIXM::Feature`s](https://www.rubydoc.info/gems/aixm/AIXM/Feature)
|
87
139
|
* some core extensions from ActiveSupport – [`Object#blank`](https://www.rubydoc.info/gems/activesupport/Object#blank%3F-instance_method) and [`String`](https://www.rubydoc.info/gems/activesupport/String)
|
88
140
|
* core extensions from this gem – [`Object`](https://www.rubydoc.info/gems/aipp/Object), [`NilClass`](https://www.rubydoc.info/gems/aipp/NilClass), [`Integer`](https://www.rubydoc.info/gems/aipp/Integer), [`String`](https://www.rubydoc.info/gems/aipp/String), [`Hash`](https://www.rubydoc.info/gems/aipp/Hash) and [`Enumerable`](https://www.rubydoc.info/gems/aipp/Enumerable)
|
89
141
|
|
@@ -129,7 +181,7 @@ See [`AIPP::Border`](https://www.rubydoc.info/gems/aipp/AIPP/Border) for more on
|
|
129
181
|
|
130
182
|
### Helpers
|
131
183
|
|
132
|
-
Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically.
|
184
|
+
Helpers are modules defined in the <tt>lib/aipp/regions/{REGION}/helpers/</tt> directory. All helper modules are required automatically in alphabetic order.
|
133
185
|
|
134
186
|
There is one mandatory helper called `URL.rb` which must define the following method to build URLs from which to download AIPs:
|
135
187
|
|
@@ -155,7 +207,7 @@ Feel free to add more helpers to DRY code which is shared by multiple AIP parser
|
|
155
207
|
module AIPP
|
156
208
|
module LF
|
157
209
|
module Helpers
|
158
|
-
module
|
210
|
+
module Base
|
159
211
|
|
160
212
|
def source(position:, aip_file: nil)
|
161
213
|
(...)
|
@@ -174,7 +226,7 @@ module AIPP
|
|
174
226
|
module LF
|
175
227
|
class AD2 < AIP
|
176
228
|
|
177
|
-
include AIPP::LF::Helpers::
|
229
|
+
include AIPP::LF::Helpers::Base
|
178
230
|
|
179
231
|
end
|
180
232
|
end
|
data/aipp.gemspec
CHANGED
@@ -25,18 +25,19 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency 'minitest'
|
26
26
|
spec.add_development_dependency 'minitest-reporters'
|
27
27
|
spec.add_development_dependency 'minitest-sound'
|
28
|
+
spec.add_development_dependency 'minitest-focus'
|
28
29
|
spec.add_development_dependency 'minitest-matchers'
|
29
30
|
spec.add_development_dependency 'spy'
|
30
31
|
spec.add_development_dependency 'guard'
|
31
32
|
spec.add_development_dependency 'guard-minitest'
|
32
33
|
|
33
|
-
spec.add_runtime_dependency 'aixm', '>= 0.3.
|
34
|
+
spec.add_runtime_dependency 'aixm', '>= 0.3.8'
|
34
35
|
spec.add_runtime_dependency 'activesupport', '~> 5'
|
35
36
|
spec.add_runtime_dependency 'nokogiri', '~> 1'
|
36
37
|
spec.add_runtime_dependency 'nokogumbo', '~> 2'
|
37
38
|
spec.add_runtime_dependency 'pdf-reader', '~> 2'
|
38
39
|
spec.add_runtime_dependency 'json', '~> 2'
|
39
|
-
spec.add_runtime_dependency 'rubyzip', '~>
|
40
|
+
spec.add_runtime_dependency 'rubyzip', '~> 2'
|
40
41
|
spec.add_runtime_dependency 'colorize', '~> 0'
|
41
42
|
spec.add_runtime_dependency 'pry', '~> 0'
|
42
43
|
spec.add_runtime_dependency 'pry-rescue', '~> 1'
|
data/lib/aipp.rb
CHANGED
data/lib/aipp/aip.rb
CHANGED
@@ -35,9 +35,8 @@ module AIPP
|
|
35
35
|
|
36
36
|
# Read an AIP source file
|
37
37
|
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
# * read from local archive
|
38
|
+
# Read the cached source file if it exists in the source archive. Otherwise,
|
39
|
+
# download it from URL and cache it.
|
41
40
|
#
|
42
41
|
# An URL builder method +url_for(aip_file)+ must be defined either in
|
43
42
|
# +helper.rb+ or in the AIP parser definition (e.g. +ENR-2.1.rb+).
|
@@ -69,15 +68,8 @@ module AIPP
|
|
69
68
|
# e.g. :airport or :vor as listed in AIXM::CLASSES are recognized as well
|
70
69
|
# @param attributes [Hash] filter by these attributes and their values
|
71
70
|
# @return [Array<AIXM::Feature>]
|
72
|
-
def select(
|
73
|
-
|
74
|
-
aixm.features.select do |feature|
|
75
|
-
if feature.is_a? klass
|
76
|
-
attributes.reduce(true) do |memo, (attribute, value)|
|
77
|
-
memo && feature.send(attribute) == value
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
71
|
+
def select(*args)
|
72
|
+
aixm.select_features(*args)
|
81
73
|
end
|
82
74
|
end
|
83
75
|
|
data/lib/aipp/downloader.rb
CHANGED
@@ -3,15 +3,15 @@ module AIPP
|
|
3
3
|
# AIP downloader infrastructure
|
4
4
|
#
|
5
5
|
# The downloader operates in the +storage+ directory where it creates two
|
6
|
-
# subdirectories "
|
7
|
-
# in "
|
8
|
-
# a +document+, the downloader looks for the +document+ in "work" and
|
6
|
+
# subdirectories "sources" and "work". The initializer looks for the +source+
|
7
|
+
# archive in "sources" and (if found) unzips its contents into "work". When
|
8
|
+
# reading a +document+, the downloader looks for the +document+ in "work" and
|
9
9
|
# (unless found) downloads it from +url+. HTML documents are parsed to
|
10
10
|
# +Nokogiri::HTML5::Document+, PDF documents are parsed to +AIPP::PDF+.
|
11
|
-
# Finally, the contents of "work" are written back to +archive
|
11
|
+
# Finally, the contents of "work" are written back to the +source+ archive.
|
12
12
|
#
|
13
13
|
# @example
|
14
|
-
# AIPP::Downloader.new(storage: options[:storage],
|
14
|
+
# AIPP::Downloader.new(storage: options[:storage], source: "2018-11-08") do |downloader|
|
15
15
|
# html = downloader.read(
|
16
16
|
# document: 'ENR-5.1',
|
17
17
|
# url: 'https://www.sia.aviation-civile.gouv.fr/dvd/eAIP_08_NOV_2018/FRANCE/AIRAC-2018-11-08/html/eAIP/FR-ENR-5.1-fr-FR.html'
|
@@ -26,20 +26,20 @@ module AIPP
|
|
26
26
|
# @return [Pathname] directory to operate within
|
27
27
|
attr_reader :storage
|
28
28
|
|
29
|
-
# @return [String] name of the archive (without extension ".zip")
|
30
|
-
attr_reader :
|
29
|
+
# @return [String] name of the source archive (without extension ".zip")
|
30
|
+
attr_reader :source
|
31
31
|
|
32
|
-
# @return [Pathname] full path to the archive
|
33
|
-
attr_reader :
|
32
|
+
# @return [Pathname] full path to the source archive
|
33
|
+
attr_reader :source_file
|
34
34
|
|
35
35
|
# @param storage [Pathname] directory to operate within
|
36
|
-
# @param
|
37
|
-
def initialize(storage:,
|
38
|
-
@storage, @
|
36
|
+
# @param source [String] name of the source archive (without extension ".zip")
|
37
|
+
def initialize(storage:, source:)
|
38
|
+
@storage, @source = storage, source
|
39
39
|
fail(ArgumentError, 'bad storage directory') unless Dir.exist? storage
|
40
|
-
@
|
40
|
+
@source_file = sources_path.join("#{@source}.zip")
|
41
41
|
prepare
|
42
|
-
unzip if @
|
42
|
+
unzip if @source_file.exist?
|
43
43
|
yield self
|
44
44
|
zip
|
45
45
|
ensure
|
@@ -65,8 +65,8 @@ module AIPP
|
|
65
65
|
|
66
66
|
private
|
67
67
|
|
68
|
-
def
|
69
|
-
@storage.join('
|
68
|
+
def sources_path
|
69
|
+
@storage.join('sources')
|
70
70
|
end
|
71
71
|
|
72
72
|
def work_path
|
@@ -75,7 +75,7 @@ module AIPP
|
|
75
75
|
|
76
76
|
def prepare
|
77
77
|
teardown
|
78
|
-
|
78
|
+
sources_path.mkpath
|
79
79
|
work_path.mkpath
|
80
80
|
end
|
81
81
|
|
@@ -87,15 +87,15 @@ module AIPP
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def unzip
|
90
|
-
Zip::File.open(
|
90
|
+
Zip::File.open(source_file).each do |entry|
|
91
91
|
entry.extract(work_path.join(entry.name))
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
95
|
def zip
|
96
|
-
backup_file =
|
97
|
-
|
98
|
-
Zip::File.open(
|
96
|
+
backup_file = source_file.sub(/$/, '.old') if source_file.exist?
|
97
|
+
source_file.rename(backup_file) if backup_file
|
98
|
+
Zip::File.open(source_file, Zip::File::CREATE) do |zip|
|
99
99
|
work_path.children.each do |entry|
|
100
100
|
zip.add(entry.basename.to_s, entry) unless entry.basename.to_s[0] == '.'
|
101
101
|
end
|
data/lib/aipp/executable.rb
CHANGED
@@ -8,7 +8,8 @@ module AIPP
|
|
8
8
|
@options = options
|
9
9
|
@options[:airac] = AIPP::AIRAC.new
|
10
10
|
@options[:storage] = Pathname(Dir.home).join('.aipp')
|
11
|
-
@options[:force] =
|
11
|
+
@options[:force] = @options[:mid] = false
|
12
|
+
$VERBOSE_INFO = $PRY_ON_WARN = $PRY_ON_ERROR = false
|
12
13
|
OptionParser.new do |o|
|
13
14
|
o.banner = <<~END
|
14
15
|
Download online AIP and convert it to #{options[:schema].upcase}.
|
@@ -17,6 +18,7 @@ module AIPP
|
|
17
18
|
o.on('-d', '--airac DATE', String, %Q[AIRAC date (default: "#{@options[:airac].date.xmlschema}")]) { |v| @options[:airac] = AIPP::AIRAC.new(v) }
|
18
19
|
o.on('-r', '--region STRING', String, 'region (e.g. "LF")') { |v| @options[:region] = v.upcase }
|
19
20
|
o.on('-a', '--aip STRING', String, 'process this AIP only (e.g. "ENR-5.1")') { |v| @options[:aip] = v.upcase }
|
21
|
+
o.on('-m', '--[no-]mid', 'insert mid attributes into all Uid elements (default: false)') { |v| @options[:mid] = v }
|
20
22
|
o.on('-s', '--storage DIR', String, 'storage directory (default: "~/.aipp")') { |v| @options[:storage] = Pathname(v) }
|
21
23
|
o.on('-f', '--[no-]force', 'ignore XML schema validation (default: false)') { |v| @options[:force] = v }
|
22
24
|
o.on('-v', '--[no-]verbose', 'verbose output (default: false)') { |v| $VERBOSE_INFO = v }
|
@@ -41,6 +43,7 @@ module AIPP
|
|
41
43
|
parser.parse_aip
|
42
44
|
parser.validate_aixm
|
43
45
|
parser.write_aixm
|
46
|
+
parser.write_build
|
44
47
|
parser.write_config
|
45
48
|
end
|
46
49
|
rescue => error
|
data/lib/aipp/parser.rb
CHANGED
@@ -3,6 +3,8 @@ module AIPP
|
|
3
3
|
# AIP parser infrastructure
|
4
4
|
class Parser
|
5
5
|
|
6
|
+
using AIXM::Refinements
|
7
|
+
|
6
8
|
# @return [Hash] passed command line arguments
|
7
9
|
attr_reader :options
|
8
10
|
|
@@ -24,7 +26,7 @@ module AIPP
|
|
24
26
|
def initialize(options:)
|
25
27
|
@options = options
|
26
28
|
@options[:storage] = options[:storage].join(options[:region])
|
27
|
-
@options[:storage].mkpath
|
29
|
+
@options[:storage].mkpath
|
28
30
|
@config = {}
|
29
31
|
@aixm = AIXM.document(region: @options[:region], effective_at: @options[:airac].date)
|
30
32
|
@dependencies = THash.new
|
@@ -76,7 +78,7 @@ module AIPP
|
|
76
78
|
# Parse AIP by invoking the parser classes for the current region.
|
77
79
|
def parse_aip
|
78
80
|
info("AIRAC #{options[:airac].id} effective #{options[:airac].date}", color: :green)
|
79
|
-
AIPP::Downloader.new(storage: options[:storage],
|
81
|
+
AIPP::Downloader.new(storage: options[:storage], source: options[:airac].date.xmlschema) do |downloader|
|
80
82
|
@dependencies.tsort(options[:aip]).each do |aip|
|
81
83
|
info("Parsing #{aip}")
|
82
84
|
("AIPP::%s::%s" % [options[:region], aip.remove(/\W/).classify]).constantize.new(
|
@@ -102,9 +104,52 @@ module AIPP
|
|
102
104
|
|
103
105
|
# Write the AIXM document.
|
104
106
|
def write_aixm
|
105
|
-
|
106
|
-
|
107
|
-
File.write(
|
107
|
+
info("Writing #{aixm_file}")
|
108
|
+
AIXM.config.mid_region = options[:region] if options[:mid]
|
109
|
+
File.write(aixm_file, aixm.to_xml)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Write the AIXM document and context information.
|
113
|
+
def write_build
|
114
|
+
info("Writing build")
|
115
|
+
builds_path.mkpath
|
116
|
+
build_file = builds_path.join("#{@options[:airac].date.xmlschema}.zip")
|
117
|
+
build_file.delete if build_file.exist?
|
118
|
+
Dir.mktmpdir do |tmp_dir|
|
119
|
+
tmp_dir = Pathname(tmp_dir)
|
120
|
+
AIXM.config.mid_region = options[:region]
|
121
|
+
# AIXM/OFMX file
|
122
|
+
File.write(tmp_dir.join(aixm_file), aixm.to_xml)
|
123
|
+
# Build details
|
124
|
+
File.write(
|
125
|
+
tmp_dir.join('build.yaml'), {
|
126
|
+
version: AIPP::VERSION,
|
127
|
+
config: @config,
|
128
|
+
options: @options
|
129
|
+
}.to_yaml
|
130
|
+
)
|
131
|
+
# Manifest
|
132
|
+
manifest, buffer, feature, uid, comment = [], '', '', '', ''
|
133
|
+
File.open(tmp_dir.join(aixm_file)).each do |line|
|
134
|
+
buffer << line
|
135
|
+
case line
|
136
|
+
when /^ {2}<(\w{3}) / then buffer, feature = line, $1
|
137
|
+
when /^ {4}<#{feature}Uid mid="(.*?)"/ then uid = $1
|
138
|
+
when /^ {2}<!-- (.*) -->/ then comment = $1
|
139
|
+
when /^ {2}<\/#{feature}>/
|
140
|
+
manifest << [feature, uid[0,8], buffer.payload_hash(region: options[:region])[0,8], comment].to_csv
|
141
|
+
feature, uid = '', ''
|
142
|
+
end
|
143
|
+
end
|
144
|
+
manifest = manifest.sort.prepend "Feature,Short Uid Hash,Short Feature Hash,Comment\n"
|
145
|
+
File.write(tmp_dir.join('manifest.csv'), manifest.join)
|
146
|
+
# Zip it
|
147
|
+
Zip::File.open(build_file, Zip::File::CREATE) do |zip|
|
148
|
+
tmp_dir.children.each do |entry|
|
149
|
+
zip.add(entry.basename.to_s, entry) unless entry.basename.to_s[0] == '.'
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
108
153
|
end
|
109
154
|
|
110
155
|
# Write the configuration to config.yml.
|
@@ -115,6 +160,14 @@ module AIPP
|
|
115
160
|
|
116
161
|
private
|
117
162
|
|
163
|
+
def aixm_file
|
164
|
+
"#{options[:region]}_#{options[:airac].date.xmlschema}.#{options[:schema]}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def builds_path
|
168
|
+
options[:storage].join('builds')
|
169
|
+
end
|
170
|
+
|
118
171
|
def config_file
|
119
172
|
options[:storage].join('config.yml')
|
120
173
|
end
|