Module: Lutaml::Model::Schema::XmlCompiler
- Extended by:
- XmlCompiler
- Included in:
- XmlCompiler
- Defined in:
- lib/lutaml/model/schema/xml_compiler.rb,
lib/lutaml/model/schema/xml_compiler/group.rb,
lib/lutaml/model/schema/xml_compiler/choice.rb,
lib/lutaml/model/schema/xml_compiler/element.rb,
lib/lutaml/model/schema/xml_compiler/sequence.rb,
lib/lutaml/model/schema/xml_compiler/attribute.rb,
lib/lutaml/model/schema/xml_compiler/restriction.rb,
lib/lutaml/model/schema/xml_compiler/simple_type.rb,
lib/lutaml/model/schema/xml_compiler/complex_type.rb,
lib/lutaml/model/schema/xml_compiler/simple_content.rb,
lib/lutaml/model/schema/xml_compiler/attribute_group.rb,
lib/lutaml/model/schema/xml_compiler/complex_content.rb,
lib/lutaml/model/schema/xml_compiler/complex_content_restriction.rb
Defined Under Namespace
Classes: Attribute, AttributeGroup, Choice, ComplexContent, ComplexContentRestriction, ComplexType, Element, Group, Restriction, Sequence, SimpleContent, SimpleType
Constant Summary collapse
- ELEMENT_ORDER_IGNORABLE =
%w[import include].freeze
- XML_ADAPTER_NOT_SET_MESSAGE =
"Nokogiri is not set as XML Adapter.\nMake sure Nokogiri is installed and set as XML Adapter eg.\nexecute: gem install nokogiri\nrequire 'lutaml/model/adapter/nokogiri'\nLutaml::Model.xml_adapter = Lutaml::Model::Adapter::Nokogiri\n"- XML_DEFINED_ATTRIBUTES =
{ "id" => "id", "lang" => "language", "space" => "NCName", "base" => "anyURI", }.freeze
Instance Attribute Summary collapse
-
#attribute_groups ⇒ Object
readonly
Returns the value of attribute attribute_groups.
-
#attributes ⇒ Object
readonly
Returns the value of attribute attributes.
-
#complex_types ⇒ Object
readonly
Returns the value of attribute complex_types.
-
#elements ⇒ Object
readonly
Returns the value of attribute elements.
-
#group_types ⇒ Object
readonly
Returns the value of attribute group_types.
-
#simple_types ⇒ Object
readonly
Returns the value of attribute simple_types.
Instance Method Summary collapse
- #as_models(schema, options: {}) ⇒ Object
- #create_file(name, content, dir) ⇒ Object
- #populate_default_values ⇒ Object
- #require_classes(classes_hash) ⇒ Object
- #resolved_element_order(object) ⇒ Object
- #restriction_content(instance, restriction) ⇒ Object
- #restriction_length(lengths) ⇒ Object
-
#restriction_min_max(restriction, instance, field:, value_method: :min) ⇒ Object
Use min/max to get the value from the field_value array.
- #restriction_patterns(patterns, instance) ⇒ Object
- #schema_to_models(schemas) ⇒ Object
- #setup_attribute(attribute) ⇒ Object
- #setup_attribute_groups(attribute_group) ⇒ Object
- #setup_attribute_type(attribute) ⇒ Object
- #setup_choice(choice) ⇒ Object
- #setup_complex_content(complex_content, name, compiler_complex_type) ⇒ Object
- #setup_complex_content_restriction(restriction, compiler_complex_type) ⇒ Object
- #setup_complex_type(complex_type) ⇒ Object
- #setup_element(element) ⇒ Object
-
#setup_element_type(element, _instance) ⇒ Object
Populates @simple_types or @complex_types based on elements available value.
- #setup_extension(extension, instance) ⇒ Object
- #setup_group_type(group, root_call: false) ⇒ Object
- #setup_group_type_instance(group) ⇒ Object
- #setup_restriction(restriction) ⇒ Object
- #setup_sequence(sequence) ⇒ Object
- #setup_simple_content(simple_content) ⇒ Object
- #setup_simple_type(simple_type) ⇒ Object
- #to_models(schema, options = {}) ⇒ Object
Instance Attribute Details
#attribute_groups ⇒ Object (readonly)
Returns the value of attribute attribute_groups.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def attribute_groups @attribute_groups end |
#attributes ⇒ Object (readonly)
Returns the value of attribute attributes.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def attributes @attributes end |
#complex_types ⇒ Object (readonly)
Returns the value of attribute complex_types.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def complex_types @complex_types end |
#elements ⇒ Object (readonly)
Returns the value of attribute elements.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def elements @elements end |
#group_types ⇒ Object (readonly)
Returns the value of attribute group_types.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def group_types @group_types end |
#simple_types ⇒ Object (readonly)
Returns the value of attribute simple_types.
25 26 27 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 25 def simple_types @simple_types end |
Instance Method Details
#as_models(schema, options: {}) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 79 def as_models(schema, options: {}) raise Error, XML_ADAPTER_NOT_SET_MESSAGE unless Config.xml_adapter.name.end_with?("NokogiriAdapter") parsed_schema = Xsd.parse(schema, location: [:location]) @elements = MappingHash.new @attributes = MappingHash.new @group_types = MappingHash.new @simple_types = MappingHash.new @complex_types = MappingHash.new @attribute_groups = MappingHash.new populate_default_values schema_to_models(Array(parsed_schema)) end |
#create_file(name, content, dir) ⇒ Object
66 67 68 69 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 66 def create_file(name, content, dir) name = name.split(":").last File.write("#{dir}/#{Utils.snake_case(name)}.rb", content) end |
#populate_default_values ⇒ Object
95 96 97 98 99 100 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 95 def populate_default_values XML_DEFINED_ATTRIBUTES.each do |name, value| @attributes[name] = Attribute.new(name: name) @attributes[name].type = value end end |
#require_classes(classes_hash) ⇒ Object
71 72 73 74 75 76 77 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 71 def require_classes(classes_hash) Dir.mktmpdir do |dir| classes_hash.each { |name, klass| create_file(name, klass, dir) } # Some files are not created at the time of the require, so we need to require them after all the files are created. classes_hash.each_key { |name| require "#{dir}/#{Utils.snake_case(name)}" } end end |
#resolved_element_order(object) ⇒ Object
390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 390 def resolved_element_order(object) return [] if object.element_order.nil? object.element_order.each_with_object(object.element_order.dup) do |builder_instance, array| next array.delete(builder_instance) if builder_instance.text? || ELEMENT_ORDER_IGNORABLE.include?(builder_instance.name) index = 0 array.each_with_index do |element, i| next unless element == builder_instance array[i] = Array(object.send(Utils.snake_case(builder_instance.name)))[index] index += 1 end end end |
#restriction_content(instance, restriction) ⇒ Object
140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 140 def restriction_content(instance, restriction) return instance unless restriction.respond_to?(:max_length) restriction_min_max(restriction, instance, field: :max_length, value_method: :min) restriction_min_max(restriction, instance, field: :min_length, value_method: :max) restriction_min_max(restriction, instance, field: :min_inclusive, value_method: :max) restriction_min_max(restriction, instance, field: :max_inclusive, value_method: :min) restriction_min_max(restriction, instance, field: :max_exclusive, value_method: :max) restriction_min_max(restriction, instance, field: :min_exclusive, value_method: :min) instance.length = restriction_length(restriction.length) if restriction.length&.any? end |
#restriction_length(lengths) ⇒ Object
163 164 165 166 167 168 169 170 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 163 def restriction_length(lengths) lengths.map do |length| MappingHash.new.tap do |hash| hash[:value] = length.value hash[:fixed] = length.fixed if length.fixed end end end |
#restriction_min_max(restriction, instance, field:, value_method: :min) ⇒ Object
Use min/max to get the value from the field_value array.
153 154 155 156 157 158 159 160 161 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 153 def restriction_min_max(restriction, instance, field:, value_method: :min) field_value = restriction.public_send(field) return unless field_value&.any? instance.public_send( :"#{field}=", field_value.map(&:value).send(value_method).to_s, ) end |
#restriction_patterns(patterns, instance) ⇒ Object
355 356 357 358 359 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 355 def restriction_patterns(patterns, instance) return if Utils.blank?(patterns) instance.pattern = patterns.map { |p| "(#{p.value})" }.join("|") end |
#schema_to_models(schemas) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 102 def schema_to_models(schemas) return if schemas.empty? schemas.each do |schema| schema_to_models(schema.include) if schema.include&.any? schema_to_models(schema.import) if schema.import&.any? resolved_element_order(schema).each do |order_item| item_name = order_item.name if order_item.respond_to?(:name) case order_item when Xsd::SimpleType @simple_types[item_name] = setup_simple_type(order_item) when Xsd::Group @group_types[item_name] = setup_group_type(order_item, root_call: true) when Xsd::ComplexType @complex_types[item_name] = setup_complex_type(order_item) when Xsd::Element @elements[item_name] = setup_element(order_item) when Xsd::Attribute @attributes[item_name] = setup_attribute(order_item) when Xsd::AttributeGroup @attribute_groups[item_name] = setup_attribute_groups(order_item) end end end nil end |
#setup_attribute(attribute) ⇒ Object
264 265 266 267 268 269 270 271 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 264 def setup_attribute(attribute) instance = Attribute.new(name: attribute.name, ref: attribute.ref) if attribute.name instance.type = setup_attribute_type(attribute) instance.default = attribute.default end instance end |
#setup_attribute_groups(attribute_group) ⇒ Object
283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 283 def setup_attribute_groups(attribute_group) instance = AttributeGroup.new(name: attribute_group.name, ref: attribute_group.ref) if attribute_group.name resolved_element_order(attribute_group).each do |object| group_attribute = case object when Xsd::Attribute setup_attribute(object) when Xsd::AttributeGroup setup_attribute_groups(object) end instance << group_attribute if group_attribute end end instance end |
#setup_attribute_type(attribute) ⇒ Object
273 274 275 276 277 278 279 280 281 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 273 def setup_attribute_type(attribute) return attribute.type if attribute.type simple_type = attribute.simple_type attr_name = "ST_#{attribute.name}" simple_type.name = attr_name @simple_types[attr_name] = setup_simple_type(simple_type) attr_name end |
#setup_choice(choice) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 245 def setup_choice(choice) Choice.new.tap do |instance| instance.min_occurs = choice.min_occurs instance.max_occurs = choice.max_occurs resolved_element_order(choice).each do |element| instance << case element when Xsd::Element setup_element(element) when Xsd::Sequence setup_sequence(element) when Xsd::Group setup_group_type(element) when Xsd::Choice setup_choice(element) end end end end |
#setup_complex_content(complex_content, name, compiler_complex_type) ⇒ Object
361 362 363 364 365 366 367 368 369 370 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 361 def setup_complex_content(complex_content, name, compiler_complex_type) @complex_types[name] = ComplexContent.new.tap do |instance| compiler_complex_type.mixed = complex_content.mixed if extension = complex_content.extension setup_extension(extension, compiler_complex_type) elsif restriction = complex_content.restriction instance.restriction = setup_complex_content_restriction(restriction, compiler_complex_type) end end end |
#setup_complex_content_restriction(restriction, compiler_complex_type) ⇒ Object
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 335 def setup_complex_content_restriction(restriction, compiler_complex_type) ComplexContentRestriction.new.tap do |instance| compiler_complex_type.base_class = restriction.base resolved_element_order(restriction).each do |element| instance << case element when Xsd::Attribute setup_attribute(element) when Xsd::AttributeGroup setup_attribute_groups(element) when Xsd::Sequence setup_sequence(element) when Xsd::Choice setup_choice(element) when Xsd::Group setup_group_type(element) end end end end |
#setup_complex_type(complex_type) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 172 def setup_complex_type(complex_type) ComplexType.new.tap do |instance| instance.id = complex_type.id instance.name = complex_type.name instance.mixed = complex_type.mixed resolved_element_order(complex_type).each do |element| case element when Xsd::Attribute instance << setup_attribute(element) when Xsd::Sequence instance << setup_sequence(element) when Xsd::Choice instance << setup_choice(element) when Xsd::ComplexContent instance << setup_complex_content(element, instance.name, instance) when Xsd::AttributeGroup instance << setup_attribute_groups(element) when Xsd::Group instance << setup_group_type(element) when Xsd::SimpleContent instance.simple_content = setup_simple_content(element) end end end end |
#setup_element(element) ⇒ Object
299 300 301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 299 def setup_element(element) element_name = element.name instance = Element.new(name: element_name, ref: element.ref) instance.min_occurs = element.min_occurs instance.max_occurs = element.max_occurs if element_name instance.type = setup_element_type(element, instance) instance.id = element.id instance.fixed = element.fixed instance.default = element.default end instance end |
#setup_element_type(element, _instance) ⇒ Object
Populates @simple_types or @complex_types based on elements available value.
314 315 316 317 318 319 320 321 322 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 314 def setup_element_type(element, _instance) return element.type if element.type type, prefix = element.simple_type ? ["simple", "ST"] : ["complex", "CT"] type_instance = element.public_send(:"#{type}_type") type_instance.name = [prefix, element.name].join("_") instance_variable_get(:"@#{type}_types")[type_instance.name] = public_send(:"setup_#{type}_type", type_instance) type_instance.name end |
#setup_extension(extension, instance) ⇒ Object
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 372 def setup_extension(extension, instance) instance.base_class = extension.base resolved_element_order(extension).each do |element| instance << case element when Xsd::Attribute setup_attribute(element) when Xsd::AttributeGroup setup_attribute_groups(element) when Xsd::Sequence setup_sequence(element) when Xsd::Choice setup_choice(element) when Xsd::Group setup_group_type(element) end end end |
#setup_group_type(group, root_call: false) ⇒ Object
230 231 232 233 234 235 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 230 def setup_group_type(group, root_call: false) object = Group.new(group.name, group.ref) object.instance = setup_group_type_instance(group) @group_types[group.name] = object if group.name && !root_call object end |
#setup_group_type_instance(group) ⇒ Object
237 238 239 240 241 242 243 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 237 def setup_group_type_instance(group) if sequence = group.sequence setup_sequence(sequence) elsif choice = group.choice setup_choice(choice) end end |
#setup_restriction(restriction) ⇒ Object
324 325 326 327 328 329 330 331 332 333 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 324 def setup_restriction(restriction) Restriction.new.tap do |instance| instance.base_class = restriction.base restriction_patterns(restriction.pattern, instance) if restriction.respond_to?(:pattern) restriction_content(instance, restriction) if restriction.respond_to?(:enumeration) && restriction.enumeration&.any? instance.enumerations = restriction.enumeration.map(&:value) end end end |
#setup_sequence(sequence) ⇒ Object
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 210 def setup_sequence(sequence) Sequence.new.tap do |instance| resolved_element_order(sequence).each do |object| # No implementation yet for Xsd::Any! next if object.is_a?(Xsd::Any) instance << case object when Xsd::Sequence setup_sequence(object) when Xsd::Element setup_element(object) when Xsd::Choice setup_choice(object) when Xsd::Group setup_group_type(object) end end end end |
#setup_simple_content(simple_content) ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 198 def setup_simple_content(simple_content) SimpleContent.new.tap do |instance| if simple_content.extension instance.base_class = simple_content.extension.base setup_extension(simple_content.extension, instance) elsif simple_content.restriction instance.base_class = simple_content.restriction.base instance << setup_restriction(simple_content.restriction) end end end |
#setup_simple_type(simple_type) ⇒ Object
129 130 131 132 133 134 135 136 137 138 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 129 def setup_simple_type(simple_type) SimpleType.new(simple_type.name).tap do |type_object| if union = simple_type.union type_object.unions = union.member_types.split elsif restriction = simple_type.restriction type_object.base_class = restriction.base&.split(":")&.last type_object.instance = setup_restriction(restriction) end end end |
#to_models(schema, options = {}) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/lutaml/model/schema/xml_compiler.rb', line 49 def to_models(schema, = {}) as_models(schema, options: ) [:indent] = [:indent] ? [:indent].to_i : 2 @simple_types.merge!(XmlCompiler::SimpleType.setup_supported_types) classes_list = @simple_types.merge(@complex_types).merge(@group_types) classes_list = classes_list.transform_values { |type| type.to_class(options: ) } if [:create_files] dir = .fetch(:output_dir, "lutaml_models_#{Time.now.to_i}") FileUtils.mkdir_p(dir) classes_list.each { |name, klass| create_file(name, klass, dir) } true else require_classes(classes_list) if [:load_classes] classes_list end end |