class AIPP::Parser

AIP parser infrastructure

Attributes

aixm[R]

@return [AIXM::Document] target document

borders[R]

@return [Hash] map from border names to border objects

cache[R]

@return [OpenStruct] object cache

config[R]

@return [Hash] configuration read from config.yml

fixtures[R]

@return [Hash] map from AIP name to fixtures

options[R]

@return [Hash] passed command line arguments

Public Class Methods

new(options:) click to toggle source
   # File lib/aipp/parser.rb
26 def initialize(options:)
27   @options = options
28   @options[:storage] = options[:storage].join(options[:region])
29   @options[:storage].mkpath
30   @config = {}
31   @aixm = AIXM.document(effective_at: @options[:airac].date)
32   @dependencies = THash.new
33   @fixtures = {}
34   @borders = {}
35   @cache = OpenStruct.new
36   AIXM.send("#{options[:schema]}!")
37   AIXM.config.region = options[:region]
38 end

Public Instance Methods

parse_aip() click to toggle source

Parse AIP by invoking the parser classes for the current region.

   # File lib/aipp/parser.rb
80 def parse_aip
81   info("AIRAC #{options[:airac].id} effective #{options[:airac].date}", color: :green)
82   AIPP::Downloader.new(storage: options[:storage], source: options[:airac].date.xmlschema) do |downloader|
83     @dependencies.tsort(options[:aip]).each do |aip|
84       info("Parsing #{aip}")
85       ("AIPP::%s::%s" % [options[:region], aip.remove(/\W/).classify]).constantize.new(
86         aip: aip,
87         downloader: downloader,
88         fixture: @fixtures[aip],
89         parser: self
90       ).attach_patches.tap(&:parse).detach_patches
91     end
92   end
93   if options[:grouped_obstacles]
94     info("Grouping obstacles")
95     aixm.group_obstacles!
96   end
97   info("Counting #{aixm.features.count} features")
98 end
read_config() click to toggle source

Read the configuration from config.yml.

   # File lib/aipp/parser.rb
41 def read_config
42   info("Reading config.yml")
43   @config = YAML.load_file(config_file, fallback: {}).transform_keys(&:to_sym) if config_file.exist?
44   @config[:namespace] ||= SecureRandom.uuid
45   @aixm.namespace = @config[:namespace]
46 end
read_region() click to toggle source

Read the region directory and build the dependency list.

   # File lib/aipp/parser.rb
49 def read_region
50   info("Reading region #{options[:region]}")
51   dir = Pathname(__FILE__).dirname.join('regions', options[:region])
52   fail("unknown region `#{options[:region]}'") unless dir.exist?
53   # Fixtures
54   dir.glob('fixtures/*.yml').each do |file|
55     verbose_info "Reading fixture fixtures/#{file.basename}"
56     fixture = YAML.load_file(file)
57     @fixtures[file.basename('.yml').to_s] = fixture
58   end
59   # Borders
60   dir.glob('borders/*.geojson').each do |file|
61     verbose_info "Reading border borders/#{file.basename}"
62     border = AIPP::Border.new(file)
63     @borders[border.name] = border
64   end
65   # Helpers
66   dir.glob('helpers/*.rb').each do |file|
67     verbose_info "Reading helper helpers/#{file.basename}"
68     require file
69   end
70   # Parsers
71   dir.glob('*.rb').each do |file|
72     verbose_info "Requiring #{file.basename}"
73     require file
74     aip = file.basename('.*').to_s
75     @dependencies[aip] = ("AIPP::%s::%s::DEPENDS" % [options[:region], aip.remove(/\W/).classify]).constantize
76   end
77 end
validate_aixm() click to toggle source

Validate the AIXM document.

@raise [RuntimeError] if the document is not valid

    # File lib/aipp/parser.rb
103 def validate_aixm
104   info("Detecting duplicates")
105   if (duplicates = aixm.features.duplicates).any?
106     message = "duplicates found:\n" + duplicates.map { "#{_1.inspect} from #{_1.source}" }.join("\n")
107     @options[:force] ? warn(message, pry: binding) : fail(message)
108   end
109   info("Validating #{options[:schema].upcase}")
110   unless aixm.valid?
111     message = "invalid #{options[:schema].upcase} document:\n" + aixm.errors.map(&:message).join("\n")
112     @options[:force] ? warn(message, pry: binding) : fail(message)
113   end
114 end
write_aixm() click to toggle source

Write the AIXM document.

    # File lib/aipp/parser.rb
164 def write_aixm
165   info("Writing #{aixm_file}")
166   AIXM.config.mid = options[:mid]
167   File.write(aixm_file, aixm.to_xml)
168 end
write_build() click to toggle source

Write the AIXM document and context information.

    # File lib/aipp/parser.rb
117 def write_build
118   if @options[:aip]
119     info ("Skipping build")
120   else
121     info("Writing build")
122     builds_path.mkpath
123     build_file = builds_path.join("#{@options[:airac].date.xmlschema}.zip")
124     Dir.mktmpdir do |tmp_dir|
125       tmp_dir = Pathname(tmp_dir)
126       # AIXM/OFMX file
127       AIXM.config.mid = true
128       File.write(tmp_dir.join(aixm_file), aixm.to_xml)
129       # Build details
130       File.write(
131         tmp_dir.join('build.yaml'), {
132           version: AIPP::VERSION,
133           config: @config,
134           options: @options
135         }.to_yaml
136       )
137       # Manifest
138       manifest, buffer, feature, aip, uid, comment = [], '', '', '', '', ''
139       File.open(tmp_dir.join(aixm_file)).each do |line|
140         buffer << line
141         case line
142         when /^ {2}<(\w{3}).*source=".*?\|.*?\|(.*?)\|/ then buffer, feature, aip = line, $1, $2
143         when /^ {4}<#{feature}Uid[^>]+?mid="(.*?)"/ then uid = $1
144         when /^ {2}<!-- (.*) -->/ then comment = $1
145         when /^ {2}<\/#{feature}>/
146           manifest << [aip, feature, uid[0,8], AIXM::PayloadHash.new(buffer).to_uuid[0,8], comment].to_csv
147           feature, aip, uid = '', '', ''
148         end
149       end
150       manifest = manifest.sort.prepend "AIP,Feature,Short Uid Hash,Short Feature Hash,Comment\n"
151       File.write(tmp_dir.join('manifest.csv'), manifest.join)
152       # Zip it
153       build_file.delete if build_file.exist?
154       Zip::File.open(build_file, Zip::File::CREATE) do |zip|
155         tmp_dir.children.each do |entry|
156           zip.add(entry.basename.to_s, entry) unless entry.basename.to_s[0] == '.'
157         end
158       end
159     end
160   end
161 end
write_config() click to toggle source

Write the configuration to config.yml.

    # File lib/aipp/parser.rb
171 def write_config
172   info("Writing config.yml")
173   File.write(config_file, config.to_yaml)
174 end

Private Instance Methods

aixm_file() click to toggle source
    # File lib/aipp/parser.rb
178 def aixm_file
179   "#{options[:region]}_#{options[:airac].date.xmlschema}.#{options[:schema]}"
180 end
builds_path() click to toggle source
    # File lib/aipp/parser.rb
182 def builds_path
183   options[:storage].join('builds')
184 end
config_file() click to toggle source
    # File lib/aipp/parser.rb
186 def config_file
187   options[:storage].join('config.yml')
188 end