lib/lutaml/xmi/parsers/xml.rb in lutaml-xmi-0.1.0 vs lib/lutaml/xmi/parsers/xml.rb in lutaml-xmi-0.1.1

- old
+ new

@@ -9,21 +9,22 @@ class XML ATTRIBUTE_MAPPINGS = { "uml:LiteralInteger" => "1", "uml:LiteralUnlimitedNatural" => "*" } - attr_reader :main_model + attr_reader :main_model, :xmi_cache # @param [String] io - file object with path to .xmi file # [Hash] options - options for parsing # # @return [Lutaml::XMI::Model::Document] def self.parse(io, options = {}) new.parse(Nokogiri::XML(io.read)) end def parse(xmi_doc) + @xmi_cache = {} @main_model = xmi_doc ::Lutaml::Uml::Document .new(serialize_to_hash(xmi_doc)) end @@ -31,30 +32,40 @@ def serialize_to_hash(xmi_doc) main_model = xmi_doc.xpath('//uml:Model[@xmi:type="uml:Model"]').first { name: main_model["name"], - classes: serialize_model_classes(main_model), - enums: serialize_model_enums(main_model) - # associations: serialize_model_associations(main_model) + packages: serialize_model_packages(main_model) } end + def serialize_model_packages(main_model) + main_model.xpath('./packagedElement[@xmi:type="uml:Package"]').map do |package| + { + name: package["name"], + packages: serialize_model_packages(package), + classes: serialize_model_classes(package), + enums: serialize_model_enums(package) + } + end + end + def serialize_model_classes(model) - model.xpath('.//packagedElement[@xmi:type="uml:Class"]').map do |klass| + model.xpath('./packagedElement[@xmi:type="uml:Class"]').map do |klass| { xmi_id: klass['xmi:id'], xmi_uuid: klass['xmi:uuid'], name: klass['name'], attributes: serialize_class_attributes(klass), - associations: serialize_model_associations(klass) + associations: serialize_model_associations(klass), + definition: lookup_model_definition(klass) } end end def serialize_model_enums(model) - model.xpath('.//packagedElement[@xmi:type="uml:Enumeration"]').map do |enum| + model.xpath('./packagedElement[@xmi:type="uml:Enumeration"]').map do |enum| attributes = enum .xpath('.//ownedLiteral[@xmi:type="uml:EnumerationLiteral"]') .map do |attribute| { # TODO: xmi_id @@ -75,12 +86,11 @@ return unless klass.attributes['name'] klass.xpath('.//ownedAttribute/type').map do |assoc| if assoc.attributes && assoc.attributes['idref'] id_ref = assoc.attributes['idref'].value - linked_class = main_model.xpath(%Q(//packagedElement[@xmi:type="uml:Class" and @xmi:id="#{id_ref}"])).first - member_end = linked_class.attributes['name'].value if linked_class + member_end = lookup_entity_name(id_ref) end if member_end { xmi_id: assoc['xmi:id'], xmi_uuid: assoc['xmi:uuid'], @@ -98,13 +108,33 @@ upperValue = attribute.xpath('.//upperValue').first || {} { # TODO: xmi_id # xmi_id: klass['xmi:id'], name: attribute['name'], - type: type['xmi:idref'], + type: lookup_entity_name(type['xmi:idref']) || type['xmi:idref'], cardinality: [ATTRIBUTE_MAPPINGS[lowerValue["xmi:type"]], ATTRIBUTE_MAPPINGS[upperValue["xmi:type"]]].compact } end + end + + def lookup_model_definition(klass) + xmi_id = klass['xmi:id'] + node = main_model.xpath(%Q(//element[@xmi:idref="#{xmi_id}"]/properties)).first + return unless node + + node.attributes['documentation']&.value + end + + def lookup_entity_name(xmi_id) + xmi_cache[xmi_id] ||= model_node_name_by_xmi_id(xmi_id) + xmi_cache[xmi_id] + end + + def model_node_name_by_xmi_id(xmi_id) + node = main_model.xpath(%Q(//*[@xmi:id="#{xmi_id}"])).first + return unless node + + node.attributes['name']&.value end end end end end \ No newline at end of file