lib/scaffold_parser/scaffolders/xsd.rb in scaffold_parser-0.5.0 vs lib/scaffold_parser/scaffolders/xsd.rb in scaffold_parser-0.6.0
- old
+ new
@@ -1,59 +1,61 @@
require 'scaffold_parser/scaffolders/xsd/parser'
-require 'scaffold_parser/scaffolders/xsd/builder'
+require 'scaffold_parser/scaffolders/xsd/parser/handlers/utils'
module ScaffoldParser
module Scaffolders
class XSD
- def self.call(doc, options)
- self.new(doc, options).call
+ include Parser::Handlers::Utils
+
+ def self.call(doc, options, parse_options = {})
+ self.new(doc, options, parse_options).call
end
- def initialize(doc, options)
+ def initialize(doc, options, parse_options = {})
@doc = doc
@options = options
+ @parse_options = parse_options
end
def call
- puts "Starting collectiong elements to scaffold" if @options[:verbose]
+ all = [@doc.schema] + @doc.schema.collect_included_schemas(@parse_options) + @doc.schema.collect_imported_schemas(@parse_options)
- unscaffolded_elements = collect_unscaffolded_subelements(@doc) + @doc.submodel_nodes
+ classes = Parser.call(all, @options)
- puts "Collected #{unscaffolded_elements.size} elements to scaffold" if @options[:verbose]
+ classes.each do |klass|
+ klass.methods = klass.methods.map do |meth|
+ if meth.is_a?(Parser::Handlers::SubmodelMethod) && !classes.map(&:name).include?(meth.submodel_class)
+ meth.to_at_method
+ else
+ meth
+ end
+ end
+ end
- code = unscaffolded_elements.flat_map do |element|
- [Parser.call(element.definition, @options), Builder.call(element.definition, @options)]
+ classes.each do |klass|
+ klass.namespace = @options[:namespace]
end
- code.push ['parsers/base_parser.rb', base_parser_template]
- code.push ['builders/base_builder.rb', base_builder_template]
+ classes.flat_map do |class_template|
+ [["parsers/#{class_template.name.underscore}.rb", class_template.to_s],
+ ["builders/#{class_template.name.underscore}.rb", class_template.to_builder_s],
+ ["parsers/base_parser.rb", wrap_in_namespace(base_parser_template, @options[:namespace])],
+ ["builders/base_builder.rb", wrap_in_namespace(base_builder_template, @options[:namespace])],
+ ["requires.rb", create_requires_template(classes)],
+ ["hash_with_attrs.rb", wrap_in_namespace(hash_with_attrs_template, @options[:namespace])],
+ ["mega.rb", wrap_in_namespace(mega_template, @options[:namespace])]
+ ]
+ end
end
private
- def collect_unscaffolded_subelements(node, collected = [])
- subelements = node.definition.submodel_nodes.to_a + node.definition.array_nodes.map(&:list_element)
- .reject(&:xs_type?)
- .reject { |node| collected.include?(node.to_class_name) }
-
- subelements.each do |element|
- if collected.none? { |c| c.to_class_name == element.to_class_name }
- collected << element
-
- puts "Collected #{element.to_name} element" if @options[:verbose]
-
- collect_unscaffolded_subelements(element, collected)
- end
- end
-
- collected
- end
-
def base_parser_template
<<~TEMPLATE
module Parsers
module BaseParser
+ include Mega
EMPTY_ARRAY = []
attr_accessor :raw
def initialize(raw)
@@ -93,31 +95,44 @@
elements.map do |element|
klass.new(element)
end
end
+
+ def to_h_with_attrs
+ hash = HashWithAttributes.new({}, attributes)
+
+ hash
+ end
end
end
TEMPLATE
end
def base_builder_template
<<~TEMPLATE
module Builders
module BaseBuilder
- attr_accessor :name, :data
+ attr_accessor :name, :data, :options
- def initialize(name, data = {})
+ def initialize(name, data = {}, options = {})
@name = name
@data = data || {}
+ @options = options || {}
end
def to_xml
- doc = Ox::Document.new(version: '1.0')
+ encoding = options[:encoding]
+
+ doc_options = { version: '1.0' }
+ doc_options[:encoding] = encoding if encoding
+ doc = Ox::Document.new(doc_options)
doc << builder
- Ox.dump(doc, with_xml: true)
+ dump_options = { with_xml: true }
+ dump_options[:encoding] = encoding if encoding
+ Ox.dump(doc, dump_options)
end
def build_element(name, content)
element = Ox::Element.new(name)
if content.respond_to? :attributes
@@ -132,9 +147,101 @@
element
end
end
end
TEMPLATE
+ end
+
+ def hash_with_attrs_template
+ <<~TEMPLATE
+ class HashWithAttributes
+ def initialize(hash, attributes = nil)
+ @hash = hash
+ @attributes = attributes if attributes
+ end
+
+ def value
+ @hash
+ end
+
+ def attributes
+ @attributes ||= {}
+ end
+
+ def attributes=(attributes)
+ @attributes = attributes
+ end
+
+ def ==(other)
+ if other.respond_to?(:value) && other.respond_to?(:attributes)
+ value == other.value && other.attributes == attributes
+ else
+ value == other
+ end
+ end
+
+ def merge(other)
+ merged_hash = value.merge other.value
+ merged_attrs = attributes.merge other.attributes
+
+ self.class.new(merged_hash, merged_attrs)
+ end
+
+ def key?(key)
+ value.key? key
+ end
+
+ def [](key)
+ value[key]
+ end
+
+ def []=(key, key_value)
+ value[key] = key_value
+ end
+
+ def dig(*attrs)
+ value.dig(*attrs)
+ end
+ end
+ TEMPLATE
+ end
+
+ def mega_template
+ <<~TEMPLATE
+ module Mega
+ def mega
+ called_from = caller_locations[0].label
+ included_modules = (self.class.included_modules - Class.included_modules - [Mega])
+ included_modules.map { |m| m.instance_method(called_from).bind(self).call }
+ end
+ end
+ TEMPLATE
+ end
+
+ 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 = ['parsers/base_parser', 'builders/base_builder']
+ modules.each do |klass|
+ requires << "parsers/#{klass.name.underscore}"
+ requires << "builders/#{klass.name.underscore}"
+ end
+ others.each do |klass|
+ requires << "parsers/#{klass.name.underscore}"
+ requires << "builders/#{klass.name.underscore}"
+ end
+ with_inheritance.each do |klass|
+ requires << "parsers/#{klass.name.underscore}"
+ requires << "builders/#{klass.name.underscore}"
+ end
+
+ if @options[:namespace]
+ requires = requires.map { |r| r.prepend("#{@options[:namespace].underscore}/") }
+ end
+
+ requires.map { |r| "require '#{r}'" }.join("\n")
end
end
end
end