class ScaffoldParser::Scaffolders::XSD

Public Class Methods

call(doc, options, parse_options = {}) click to toggle source
# File lib/scaffold_parser/scaffolders/xsd.rb, line 9
def self.call(doc, options, parse_options = {})
  self.new(doc, options, parse_options).call
end
new(doc, options, parse_options = {}) click to toggle source
# File lib/scaffold_parser/scaffolders/xsd.rb, line 13
def initialize(doc, options, parse_options = {})
  @doc = doc
  @options = options
  @parse_options = parse_options
end

Public Instance Methods

call() click to toggle source
# File lib/scaffold_parser/scaffolders/xsd.rb, line 19
def call
  all = [@doc.schema] + @doc.schema.collect_included_schemas(@parse_options) + @doc.schema.collect_imported_schemas(@parse_options)

  classes = Parser.call(all, @options)
  top_level_elements = all.flat_map(&:elements)
  ref_map = top_level_elements.map { |e| [e.name_with_prefix, e.type_with_prefix]}.to_h

  # reject dumb classes which are just extension proxies to simple types :D
  classes = classes.reject do |klass|
    inherit_from = classes.find do |cl|
      cl.name_with_prefix == klass&.inherit_from&.split(':')&.map(&:camelize)&.join('::')
    end

    klass.methods.empty? && klass.includes.empty? && inherit_from.nil?
  end

  # remove dumb classes inheritance
  classes = classes.map do |klass|
    inherit_from = classes.find do |cl|
      cl.name_with_prefix == klass&.inherit_from&.split(':')&.map(&:camelize)&.join('::')
    end

    if inherit_from.nil?
      klass.inherit_from = nil
    end
    klass
  end

  # remove dumb classes includes
  classes = classes.map do |klass|
    existing_includes = (klass.includes || []).select do |incl|
      classes.map(&:name_with_prefix).include? incl.full_ref
    end

    klass.includes = existing_includes

    klass
  end

  # remove proxy lists through named complex types
  # #TODO: could i somehow remove proxy complex types so they are not outputted into class files?
  #   ... they are not used anyhow.. probably not used..? Can't they be inherited from or something?
  classes = classes.map do |klass|
    klass.methods = klass.methods.map do |meth|
      if meth.is_a?(Parser::Handlers::SubmodelMethod)
        submodel_class = classes.find { |cl| cl.name_with_prefix == meth.submodel_class }

        if (submodel_class.methods.size == 1) && submodel_class.methods.first.is_a?(Parser::Handlers::ListMethod) && submodel_class.inherit_from.nil? && submodel_class.includes.empty?
          submodel_class.methods.first.to_proxy_list(meth.source, meth.at)
        else
          meth
        end
      else
        meth
      end
    end

    klass
  end

  classes.each do |klass|
    klass.methods = klass.methods.map do |meth|
      if meth.is_a?(Parser::Handlers::SubmodelMethod) && !classes.map(&:name_with_prefix).include?(meth.submodel_class)
        meth.to_at_method
      elsif  meth.is_a?(Parser::Handlers::ElementRef)
        meth.to_submodel_method(ref_map)
      else
        meth
      end
    end
  end

  requires = create_requires_template(classes)
  parsers = classes.map do |klass|
    path = ["parsers", klass.namespace&.underscore, "#{klass.name.underscore}.rb"].compact.join('/')
    string = wrap_in_namespace(klass.to_s, 'Parsers')

    [path, string]
  end
  builders = classes.map do |klass|
    path = ["builders", klass.namespace&.underscore, "#{klass.name.underscore}.rb"].compact.join('/')
    string = wrap_in_namespace(klass.to_builder_s, 'Builders')

    [path, string]
  end

  all = parsers + builders
  result = all.map do |path, string|
    [path, wrap_in_namespace(string, @options[:namespace])]
  end

  result + [['requires.rb', requires]]
end

Private Instance Methods

create_requires_template(classes) click to toggle source
# File lib/scaffold_parser/scaffolders/xsd.rb, line 115
def create_requires_template(classes)
  modules = classes.select { |cl| cl.is_a? Parser::Handlers::Module }
  classes = classes.select { |cl| cl.is_a? Parser::Handlers::Klass }
  with_inheritance, others = classes.partition { |klass| klass.inherit_from }

  requires = []
  modules.each do |klass|
    requires << ["parsers", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
    requires << ["builders", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
  end
  others.each do |klass|
    requires << ["parsers", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
    requires << ["builders", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
  end
  with_inheritance.each do |klass|
    requires << ["parsers", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
    requires << ["builders", klass.namespace&.underscore, klass.name.underscore].compact.join('/')
  end

  if @options[:namespace]
    requires = requires.map { |r| r.prepend("#{@options[:namespace].underscore}/") }
  end

  requires.map { |r| "require '#{r}'" }.join("\n")
end