Class: Lutaml::Model::Schema::XmlCompiler::SimpleType

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/model/schema/xml_compiler/simple_type.rb

Constant Summary collapse

LUTAML_VALUE_CLASS_NAME =
"Lutaml::Model::Type::Value"
SUPPORTED_DATA_TYPES =
{
  nonNegativeInteger: { skippable: false,
                        class_name: "Lutaml::Model::Type::String", validations: { pattern: /\+?[0-9]+/ } },
  normalizedString: { skippable: false,
                      class_name: "Lutaml::Model::Type::String", validations: { transform: "value.gsub(/[\\r\\n\\t]/, ' ')" } },
  positiveInteger: { skippable: false,
                     class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0 } },
  unsignedShort: { skippable: false,
                   class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 65535 } },
  base64Binary: { skippable: false,
                  class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A([A-Za-z0-9+\/]+={0,2}|\s)*\z/ } },
  unsignedLong: { skippable: false,
                  class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 18446744073709551615 } },
  unsignedByte: { skippable: false,
                  class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 255 } },
  unsignedInt: { skippable: false,
                 class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: 0, max_inclusive: 4294967295 } },
  hexBinary: { skippable: false,
               class_name: "Lutaml::Model::Type::String", validations: { pattern: /([0-9a-fA-F]{2})*/ } },
  language: { skippable: false,
              class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*\z/ } },
  dateTime: { skippable: true,
              class_name: "Lutaml::Model::Type::DateTime" },
  boolean: { skippable: true,
             class_name: "Lutaml::Model::Type::Boolean" },
  integer: { skippable: true,
             class_name: "Lutaml::Model::Type::Integer" },
  decimal: { skippable: true,
             class_name: "Lutaml::Model::Type::Decimal" },
  string: { skippable: true,
            class_name: "Lutaml::Model::Type::String" },
  double: { skippable: true,
            class_name: "Lutaml::Model::Type::Float" },
  NCName: { skippable: false,
            class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[a-zA-Z_][\w.-]*\z/ } },
  anyURI: { skippable: false,
            class_name: "Lutaml::Model::Type::String", validations: { pattern: "\\A\#{URI::DEFAULT_PARSER.make_regexp(%w[http https ftp])}\\z" } },
  token: { skippable: false,
           class_name: "Lutaml::Model::Type::String", validations: { pattern: /\A[^\t\n\f\r ]+(?: [^\t\n\f\r ]+)*\z/ } },
  byte: { skippable: false,
          class_name: "Lutaml::Model::Type::Integer", validations: { min_inclusive: -128, max_inclusive: 127 } },
  long: { skippable: false,
          class_name: "Lutaml::Model::Type::Decimal" },
  int: { skippable: true,
         class_name: "Lutaml::Model::Type::Integer" },
  id: { skippable: false, class_name: "Lutaml::Model::Type::String",
        validations: { pattern: /\A[a-zA-Z_][\w.-]*\z/ } },
}.freeze
INSTANCE_MODEL_TEMPLATE =
ERB.new(<<~TEMPLATE, trim_mode: "-")
  # frozen_string_literal: true
  require "lutaml/model"

  <%= "\#{required_files}\n" -%>
  <%= module_opening -%>
  class <%= klass_name %><%= " < \#{parent_class}" if parent_class %>
  <%= @indent %>def self.cast(value, options = {})
  <%= extended_indent %>return if value.nil?

  <%= instance&.to_method_body(extended_indent) %>
      value = super(value, options)
      value
    end
  <%= registration_methods -%>
  end
  <%= module_closing -%>
  <%= registration_execution -%>
TEMPLATE
UNION_MODEL_TEMPLATE =
ERB.new(<<~TEMPLATE, trim_mode: "-")
  # frozen_string_literal: true
  require "lutaml/model"
  <%= union_required_files %>

  <%= module_opening -%>
  class <%= klass_name %> < <%= LUTAML_VALUE_CLASS_NAME %>
  <%= @indent %>def self.cast(value, options = {})
  <%= extended_indent %>return if value.nil?

  <%= union_class_method_body %>
    end
  <%= registration_methods -%>
  end
  <%= module_closing -%>
  <%= registration_execution -%>
TEMPLATE

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, unions = []) ⇒ SimpleType

Returns a new instance of SimpleType.



99
100
101
102
103
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 99

def initialize(name, unions = [])
  @class_name = name
  @unions = unions
  @module_namespace = nil
end

Instance Attribute Details

#base_classObject

Returns the value of attribute base_class.



8
9
10
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 8

def base_class
  @base_class
end

#class_nameObject

Returns the value of attribute class_name.



8
9
10
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 8

def class_name
  @class_name
end

#instanceObject

Returns the value of attribute instance.



8
9
10
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 8

def instance
  @instance
end

#unionsObject

Returns the value of attribute unions.



8
9
10
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 8

def unions
  @unions
end

Class Method Details

.setup_restriction(base_class, validations) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 245

def setup_restriction(base_class, validations)
  return unless validations

  Restriction.new.tap do |restriction|
    restriction.base_class = base_class
    restriction.min_inclusive = validations[:min_inclusive]
    restriction.max_inclusive = validations[:max_inclusive]
    restriction.pattern = validations[:pattern]
    restriction.transform = validations[:transform]
  end
end

.setup_supported_typesObject



231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 231

def setup_supported_types
  SUPPORTED_DATA_TYPES.reject do |_, simple_type|
    simple_type[:skippable]
  end.each_with_object({}) do |(name, simple_type), hash|
    str_name = name.to_s
    new(str_name).tap do |instance|
      instance.base_class = Utils.base_class_snake_case(simple_type[:class_name])
      instance.instance = setup_restriction(instance.base_class,
                                            simple_type[:validations])
      hash[str_name] = instance
    end
  end
end

.skippable?(type) ⇒ Boolean

Returns:

  • (Boolean)


257
258
259
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 257

def skippable?(type)
  SUPPORTED_DATA_TYPES.dig(type&.to_sym, :skippable)
end

Instance Method Details

#required_filesObject



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 111

def required_files
  files = Array(instance&.required_files)
  # Don't add requires for parent classes if using module namespace
  # They're handled via central autoload registry
  if !@module_namespace && require_parent?
    files << "require_relative \"#{Utils.snake_case(parent_class)}\""
  end
  # Filter out require_relative when using autoload, keep external requires
  if @module_namespace
    files = files.select { |f| f.start_with?("require \"") }
  end
  files.join("\n")
end

#to_class(options: {}) ⇒ Object



105
106
107
108
109
# File 'lib/lutaml/model/schema/xml_compiler/simple_type.rb', line 105

def to_class(options: {})
  setup_options(options)
  template = unions&.any? ? UNION_MODEL_TEMPLATE : INSTANCE_MODEL_TEMPLATE
  template.result(binding)
end