require "goa_model_gen" require "erb" require "yaml" require "goa_model_gen/logger" require "goa_model_gen/type" require "goa_model_gen/field" require "goa_model_gen/source_file" require "active_support/core_ext/string" module GoaModelGen class BaseLoader attr_reader :path, :raw attr_reader :kind, :types_key, :fields_key def initialize(path, kind, types_key, fields_key) @path = path @kind = kind @types_key, @fields_key = types_key, fields_key erb = ERB.new(File.read(path), nil, "-") erb.filename = path txt = erb.result @raw = YAML.load(txt) end def build_type(name, d) kind.new(name, d).tap do |t| if d[fields_key] d[fields_key].each do |fname, f| t.fields << build_field(fname, f) end end end end def build_field(name, f) Field.new(name, f) end end class ModelLoader < BaseLoader def initialize(path) super(path, Model, 'types', 'fields') end def load_file types = raw[types_key].map do |name, definition| build_type(name, definition) end SourceFile.new(path, types) end def build_field(name, f) fd = f.is_a?(Hash) ? f : {'type' => f.to_s} fd['type'] ||= 'string' super(name, fd) end end class SwaggerLoader < BaseLoader def initialize(path) super(path, SwaggerDef, 'definitions', 'properties') end def build_type(name, d) super(name, d).tap do |r| required_fields = d['required'] r.fields.each do |f| f.required = (required_fields || []).include?(f.name) end end end def lookup(name) raw[types_key][name] end def load(name) d = lookup(name) unless d GoaModelGen.logger.info("#{name} not found in #{path}") return nil end build_type(name, d) end def load!(name) r = load(name) raise "#{name} not found in #{path}" unless r r end def dig(path) dig_into(raw, path.split('/'), []) end def dig_into(hash, keys, footprints) # puts "dig_into(hash, #{keys.inspect}, #{footprints.inspect})" key = keys.shift value = hash[key] return value if keys.empty? raise "No data for #{key} in #{footprints.join('/')}" if value.nil? return dig_into(value, keys, footprints + [key]) end end class Loader attr_reader :config def initialize(config) @config = config end def load_files(paths) swagger_loader = config.swagger_yaml.present? ? GoaModelGen::SwaggerLoader.new(config.swagger_yaml) : nil defined_types = {} files = paths.map do |path| GoaModelGen::ModelLoader.new(path).load_file.tap do |f| f.types.each{|t| t.assign_swagger_types(swagger_loader) } if swagger_loader f.types.each{|t| defined_types[t.name] = t } end end files.each do |f| f.types.each{|t| t.assign_field_type_base(defined_types) } end return files end end end