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