lib/lutaml/xmi/parsers/xml.rb in lutaml-xmi-0.1.5 vs lib/lutaml/xmi/parsers/xml.rb in lutaml-xmi-0.2.0

- old
+ new

@@ -32,96 +32,184 @@ def serialize_to_hash(xmi_doc) model = xmi_doc.xpath('//uml:Model[@xmi:type="uml:Model"]').first { name: model["name"], - packages: serialize_model_packages(model), + packages: serialize_model_packages(model) } end def serialize_model_packages(model) model.xpath('./packagedElement[@xmi:type="uml:Package"]').map do |package| { + xmi_id: package["xmi:id"], name: package["name"], - packages: serialize_model_packages(package), classes: serialize_model_classes(package), enums: serialize_model_enums(package), + data_types: serialize_model_data_types(package), + diagrams: serialize_model_diagrams(package), + packages: serialize_model_packages(package), + definition: doc_node_attribute_value(package, "documentation"), + stereotype: doc_node_attribute_value(package, "stereotype") } end end def serialize_model_classes(model) model.xpath('./packagedElement[@xmi:type="uml:Class"]').map do |klass| { xmi_id: klass["xmi:id"], xmi_uuid: klass["xmi:uuid"], name: klass["name"], + package: model, attributes: serialize_class_attributes(klass), associations: serialize_model_associations(klass), + operations: serialize_class_operations(klass), constraints: serialize_class_constraints(klass), is_abstract: doc_node_attribute_value(klass, "isAbstract"), definition: doc_node_attribute_value(klass, "documentation"), - stereotype: doc_node_attribute_value(klass, "stereotype"), + stereotype: doc_node_attribute_value(klass, "stereotype") } end end def serialize_model_enums(model) model.xpath('./packagedElement[@xmi:type="uml:Enumeration"]').map do |enum| attributes = enum .xpath('.//ownedLiteral[@xmi:type="uml:EnumerationLiteral"]') - .map do |attribute| - { - # TODO: xmi_id - # xmi_id: enum['xmi:id'], - type: attribute["name"], - } - end + .map do |value| + type = value.xpath(".//type").first || {} + { + name: value["name"], + type: lookup_entity_name(type["xmi:idref"]) || type["xmi:idref"], + definition: lookup_attribute_definition(value), + } + end { xmi_id: enum["xmi:id"], xmi_uuid: enum["xmi:uuid"], name: enum["name"], - attributes: attributes, + values: attributes, definition: doc_node_attribute_value(enum, "documentation"), stereotype: doc_node_attribute_value(enum, "stereotype"), } end end + def serialize_model_data_types(model) + model.xpath('./packagedElement[@xmi:type="uml:DataType"]').map do |klass| + { + xmi_id: klass["xmi:id"], + xmi_uuid: klass["xmi:uuid"], + name: klass["name"], + attributes: serialize_class_attributes(klass), + operations: serialize_class_operations(klass), + associations: serialize_model_associations(klass), + constraints: serialize_class_constraints(klass), + is_abstract: doc_node_attribute_value(klass, "isAbstract"), + definition: doc_node_attribute_value(klass, "documentation"), + stereotype: doc_node_attribute_value(klass, "stereotype"), + } + end + end + + def serialize_model_diagrams(node) + main_model.xpath(%(//diagrams/diagram/model[@package="#{node['xmi:id']}"])).map do |diagram_model| + diagram = diagram_model.parent + properties = diagram.children.find {|n| n.name == 'properties' } + { + xmi_id: diagram["xmi:id"], + name: properties["name"], + definition: properties.attributes['documentation']&.value + } + end + end + def serialize_model_associations(klass) xmi_id = klass["xmi:id"] main_model.xpath(%(//element[@xmi:idref="#{xmi_id}"]/links/*)).map do |link| member_end, member_end_type, member_end_cardinality, member_end_attribute_name = serialize_member_type(xmi_id, link) + owned_end_cardinality, owned_end_attribute_name = serialize_owned_type(xmi_id, link) if member_end && ((member_end_type != 'aggregation') || (member_end_type == 'aggregation' && member_end_attribute_name)) + definition_node = main_model.xpath(%(//connector[@xmi:idref="#{link['xmi:id']}"]/target/documentation)).first + definition = definition_node.attributes['value']&.value if definition_node { xmi_id: link["xmi:id"], member_end: member_end, member_end_type: member_end_type, member_end_cardinality: member_end_cardinality, member_end_attribute_name: member_end_attribute_name, + definition: definition } end end end + def serialize_class_operations(klass) + klass.xpath('.//ownedOperation').map do |attribute| + type = attribute.xpath(".//type").first || {} + if attribute.attributes["association"].nil? + { + # TODO: xmi_id + # xmi_id: klass['xmi:id'], + name: attribute["name"], + definition: lookup_attribute_definition(attribute), + } + end + end.compact + end + def serialize_class_constraints(klass) class_element_metadata(klass).xpath("./constraints/constraint").map do |constraint| { xmi_id: constraint["xmi:id"], body: constraint["name"], } end end + def serialize_owned_type(owned_xmi_id, link) + return if link.name == 'NoteLink' + return generalization_association(owned_xmi_id, link) if link.name == "Generalization" + + xmi_id = link.attributes["start"].value + + if link.name == "Association" + assoc_connector = main_model.xpath(%(//connector[@xmi:idref="#{link['xmi:id']}"]/source)).first + if assoc_connector + connector_type = assoc_connector.children.find { |node| node.name == 'type' } + if connector_type && connector_type.attributes['multiplicity'] + cardinality = connector_type.attributes['multiplicity']&.value&.split('..') + cardinality.unshift('1') if cardinality.length == 1 + min, max = cardinality + end + connector_role = assoc_connector.children.find { |node| node.name == 'role' } + if connector_role + owned_attribute_name = connector_role.attributes["name"]&.value + end + owned_cardinality = { "min" => LOVER_VALUE_MAPPINGS[min], "max" => max } + end + else + owned_node = main_model.xpath(%(//ownedAttribute[@association]/type[@xmi:idref="#{xmi_id}"])).first + if owned_node + assoc = owned_node.parent + owned_cardinality = { "min" => cardinality_min_value(assoc), "max" => cardinality_max_value(assoc) } + owned_attribute_name = assoc.attributes["name"]&.value + end + end + + [owned_cardinality, owned_attribute_name] + end + def serialize_member_type(owned_xmi_id, link) return if link.name == 'NoteLink' return generalization_association(owned_xmi_id, link) if link.name == "Generalization" xmi_id = link.attributes["start"].value member_end = lookup_entity_name(xmi_id) || connector_source_name(xmi_id) if link.name == "Association" - assoc_connector = main_model.xpath(%(//connector[@xmi:idref="#{link['xmi:id']}"]/source)).first + assoc_connector = main_model.xpath(%(//connector[@xmi:idref="#{link['xmi:id']}"]/target)).first if assoc_connector connector_type = assoc_connector.children.find { |node| node.name == 'type' } if connector_type && connector_type.attributes['multiplicity'] cardinality = connector_type.attributes['multiplicity']&.value&.split('..') cardinality.unshift('1') if cardinality.length == 1