require "goon_model_gen" require "erb" require "yaml" require "goon_model_gen/converter/conv_file" require "goon_model_gen/converter/payload_conv" require "goon_model_gen/converter/result_conv" require "goon_model_gen/converter/type_ref" require "goon_model_gen/converter/mapping" require "active_support/core_ext/string" module GoonModelGen module Converter class Loader attr_reader :config def initialize(config) @config = config end def process(path) erb = ERB.new(::File.read(path), nil, "-") erb.filename = path txt = erb.result raw = YAML.load(txt) converter_dir = raw['converter_dir'] || ::File.basename(path, '.*') converter_package_path = raw['converter_package_path'] || File.join(config.converter_package_path, converter_dir) ConvFile.new(path, converter_package_path).tap do |f| f.payload_convs = load_conv_defs(f, PayloadConv, raw['payloads'] || {}) f.result_convs = load_conv_defs(f, ResultConv, raw['results'] || {}) end end def load_conv_defs(f, conv_class, hash) hash.map do |(name, definition)| model = load_model_for_conv(definition['model']) gen_type = TypeRef.new(name, File.join(config.goa_gen_package_path, f.basename)) mappings = load_mappings(definition['mappings'], conv_class) conv_class.new(name, model, gen_type, mappings).tap do |conv| conv.file = f end end end def load_model_for_conv(obj) pkg_name, pkg_path, pkg_base_path = nil, nil, nil slice_with_ptr = nil case obj when Hash pkg_name, pkg_path = obj['name'], obj['package_path'] slice_with_ptr = obj['slice_with_ptr'] when String pkg_name = obj pkg_base_path = config.model_package_path else raise "Unsupported model type for converter definition: #{obj.inspect}" end TypeRef.new(pkg_name, pkg_path).tap do |t| t.package_base_path = pkg_base_path t.slice_with_ptr = slice_with_ptr end end def load_mappings(hash, conv_class) hash.map do |(name, props)| props ||= {} props = {'arg' => props} if props.is_a?(String) args = props['args'] || [props['arg'] || name] func, requires_context, returns_error = *conv_class.load_func(props) if func.nil? && (args.length > 1) raise "Invalid argument length: #{args.length} for #{name}: #{args.inspect}" end Mapping.new(name, args, func, requires_context, returns_error).tap do |m| m.allow_zero = props['allow_zero'] m.resolve_package_path(config) end end end end end end