lutaml 0.9.39 → 0.9.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/lib/lutaml/command_line.rb +1 -1
  3. data/lib/lutaml/converter/dsl_to_uml.rb +235 -0
  4. data/lib/lutaml/converter/xmi_hash_to_uml.rb +196 -0
  5. data/lib/lutaml/formatter/base.rb +7 -7
  6. data/lib/lutaml/formatter/graphviz.rb +19 -8
  7. data/lib/lutaml/formatter.rb +0 -2
  8. data/lib/lutaml/parser.rb +1 -1
  9. data/lib/lutaml/uml/action.rb +15 -0
  10. data/lib/lutaml/uml/actor.rb +0 -8
  11. data/lib/lutaml/uml/association.rb +25 -34
  12. data/lib/lutaml/uml/cardinality.rb +10 -0
  13. data/lib/lutaml/uml/class.rb +43 -68
  14. data/lib/lutaml/uml/classifier.rb +5 -3
  15. data/lib/lutaml/uml/connector.rb +5 -8
  16. data/lib/lutaml/uml/connector_end.rb +20 -0
  17. data/lib/lutaml/uml/constraint.rb +11 -1
  18. data/lib/lutaml/uml/data_type.rb +48 -64
  19. data/lib/lutaml/uml/dependency.rb +5 -8
  20. data/lib/lutaml/uml/document.rb +46 -73
  21. data/lib/lutaml/uml/enum.rb +12 -35
  22. data/lib/lutaml/uml/event.rb +0 -1
  23. data/lib/lutaml/uml/fidelity.rb +10 -0
  24. data/lib/lutaml/uml/group.rb +17 -0
  25. data/lib/lutaml/uml/instance.rb +5 -7
  26. data/lib/lutaml/uml/model.rb +3 -3
  27. data/lib/lutaml/uml/namespace.rb +10 -0
  28. data/lib/lutaml/uml/node/base.rb +1 -1
  29. data/lib/lutaml/uml/operation.rb +6 -22
  30. data/lib/lutaml/uml/package.rb +23 -44
  31. data/lib/lutaml/uml/parsers/dsl.rb +5 -2
  32. data/lib/lutaml/uml/parsers/yaml.rb +2 -28
  33. data/lib/lutaml/uml/primitive_type.rb +3 -4
  34. data/lib/lutaml/uml/property.rb +15 -17
  35. data/lib/lutaml/uml/region.rb +0 -1
  36. data/lib/lutaml/uml/state.rb +9 -1
  37. data/lib/lutaml/uml/state_machine.rb +0 -1
  38. data/lib/lutaml/uml/top_element.rb +61 -39
  39. data/lib/lutaml/uml/top_element_attribute.rb +33 -22
  40. data/lib/lutaml/uml/transition.rb +11 -1
  41. data/lib/lutaml/uml/trigger.rb +5 -1
  42. data/lib/lutaml/uml/value.rb +18 -14
  43. data/lib/lutaml/uml.rb +40 -2
  44. data/lib/lutaml/version.rb +1 -1
  45. data/lib/lutaml/xmi/liquid_drops/enum_drop.rb +1 -1
  46. data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +2 -1
  47. data/lib/lutaml/xmi/parsers/xmi_base.rb +20 -2
  48. data/lib/lutaml/xmi/parsers/xml.rb +5 -4
  49. metadata +11 -13
  50. data/lib/lutaml/uml/constructor_end.rb +0 -16
  51. data/lib/lutaml/uml/formatter/base.rb +0 -67
  52. data/lib/lutaml/uml/formatter/graphviz.rb +0 -332
  53. data/lib/lutaml/uml/formatter.rb +0 -21
  54. data/lib/lutaml/uml/serializers/association.rb +0 -58
  55. data/lib/lutaml/uml/serializers/base.rb +0 -16
  56. data/lib/lutaml/uml/serializers/class.rb +0 -29
  57. data/lib/lutaml/uml/serializers/top_element_attribute.rb +0 -14
  58. data/lib/lutaml/uml/serializers/yaml_view.rb +0 -18
  59. data/lib/lutaml/uml/version.rb +0 -7
  60. /data/{lib/lutaml/uml/README.adoc → docs/UML_README.adoc} +0 -0
@@ -2,29 +2,13 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- class Operation
6
- include HasAttributes
7
- include HasMembers
5
+ class Operation < TopElement
6
+ attribute :return_type, :string
7
+ attribute :parameter_type, :string
8
8
 
9
- attr_reader :definition
10
- attr_accessor :name,
11
- :return_type,
12
- :parameter_type
13
-
14
- # rubocop:disable Rails/ActiveRecordAliases
15
- def initialize(attributes = {})
16
- update_attributes(attributes)
17
- end
18
- # rubocop:enable Rails/ActiveRecordAliases
19
-
20
- def definition=(value)
21
- @definition = value
22
- .to_s
23
- .gsub(/\\}/, "}")
24
- .gsub(/\\{/, "{")
25
- .split("\n")
26
- .map(&:strip)
27
- .join("\n")
9
+ yaml do
10
+ map "return_type", to: :return_type
11
+ map "parameter_type", to: :parameter_type
28
12
  end
29
13
  end
30
14
  end
@@ -1,55 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "lutaml/uml/class"
4
+ require "lutaml/uml/enum"
5
+ require "lutaml/uml/data_type"
6
+ require "lutaml/uml/diagram"
7
+
3
8
  module Lutaml
4
9
  module Uml
5
10
  class Package < TopElement
6
- include HasAttributes
7
-
8
- attr_accessor :imports, :contents
9
- attr_reader :data_types, :children_packages
10
-
11
- def initialize(attributes) # rubocop:disable Lint/MissingSuper
12
- update_attributes(attributes)
13
- @children_packages ||= packages.map do |pkg|
11
+ attribute :contents, :string, collection: true, default: -> { [] }
12
+ attribute :classes, Class, collection: true, default: -> { [] }
13
+ attribute :enums, Enum, collection: true, default: -> { [] }
14
+ attribute :data_types, DataType, collection: true, default: -> { [] }
15
+ attribute :packages, Package, collection: true, default: -> { [] }
16
+ attribute :diagrams, Diagram, collection: true, default: -> { [] }
17
+
18
+ yaml do
19
+ map "contents", to: :contents
20
+ map "classes", to: :classes
21
+ map "enums", to: :enums
22
+ map "data_types", to: :data_types
23
+ map "packages", to: :packages
24
+ map "diagrams", to: :diagrams
25
+ end
26
+
27
+ def children_packages
28
+ packages.map do |pkg|
14
29
  [pkg, pkg.packages, pkg.packages.map(&:children_packages)]
15
30
  end.flatten.uniq
16
31
  end
17
-
18
- def classes=(value)
19
- @classes = value.to_a.map { |attributes| Class.new(attributes) }
20
- end
21
-
22
- def enums=(value)
23
- @enums = value.to_a.map { |attributes| Enum.new(attributes) }
24
- end
25
-
26
- def data_types=(value)
27
- @data_types = value.to_a.map { |attributes| DataType.new(attributes) }
28
- end
29
-
30
- def packages=(value)
31
- @packages = value.to_a.map { |attributes| Package.new(attributes) }
32
- end
33
-
34
- def diagrams=(value)
35
- @diagrams = value.to_a.map { |attributes| Diagram.new(attributes) }
36
- end
37
-
38
- def classes
39
- @classes || []
40
- end
41
-
42
- def enums
43
- @enums || []
44
- end
45
-
46
- def packages
47
- @packages || []
48
- end
49
-
50
- def diagrams
51
- @diagrams || []
52
- end
53
32
  end
54
33
  end
55
34
  end
@@ -5,6 +5,7 @@ require "parslet/convenience"
5
5
  require "lutaml/uml/parsers/dsl_preprocessor"
6
6
  require "lutaml/uml/parsers/dsl_transform"
7
7
  require "lutaml/uml/node/document"
8
+ require "lutaml/converter/dsl_to_uml"
8
9
 
9
10
  module Lutaml
10
11
  module Uml
@@ -13,6 +14,8 @@ module Lutaml
13
14
 
14
15
  # Class for parsing LutaML dsl into Lutaml::Uml::Document
15
16
  class Dsl < Parslet::Parser
17
+ include Lutaml::Converter::DslToUml
18
+
16
19
  # @param [String] io - LutaML string representation
17
20
  # [Hash] options - options for parsing
18
21
  #
@@ -27,8 +30,8 @@ module Lutaml
27
30
  # Parslet::ErrorReporter::Deepest allows more
28
31
  # detailed display of error
29
32
  reporter = Parslet::ErrorReporter::Deepest.new
30
- ::Lutaml::Uml::Document
31
- .new(DslTransform.new.apply(super(data, reporter: reporter)))
33
+ hash = DslTransform.new.apply(super(data, reporter: reporter))
34
+ create_uml_document(hash)
32
35
  rescue Parslet::ParseFailed => e
33
36
  raise(ParsingError,
34
37
  "#{e.message}\ncause: #{e.parse_failure_cause.ascii_tree}")
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "yaml"
4
- require "lutaml/uml/class"
5
- require "lutaml/uml/document"
6
- require "lutaml/uml/serializers/yaml_view"
4
+ require "lutaml/uml"
7
5
 
8
6
  module Lutaml
9
7
  module Uml
@@ -14,31 +12,7 @@ module Lutaml
14
12
  end
15
13
 
16
14
  def parse(yaml_path, _options = {})
17
- yaml_parse(yaml_path)
18
- end
19
-
20
- def yaml_parse(yaml_path)
21
- yaml_content = YAML.safe_load(File.read(yaml_path))
22
- serialized_yaml = Lutaml::Uml::Serializers::YamlView
23
- .new(yaml_content)
24
- result = Lutaml::Uml::Document.new(serialized_yaml)
25
- result.classes = imports_to_classes(yaml_content, yaml_path)
26
- result
27
- end
28
-
29
- private
30
-
31
- def imports_to_classes(yaml_content, yaml_path)
32
- models_path = File.join(File.dirname(yaml_path), "..", "models")
33
- yaml_content["imports"].map do |(klass_name, _)|
34
- klass_attrs = YAML.safe_load(
35
- File.read(
36
- File.join(models_path, "#{klass_name}.yml"),
37
- ),
38
- )
39
- klass_attrs["name"] = klass_name if klass_attrs["name"].nil?
40
- Lutaml::Uml::Serializers::Class.new(klass_attrs)
41
- end
15
+ Lutaml::Uml::Document.from_yaml(File.read(yaml_path))
42
16
  end
43
17
  end
44
18
  end
@@ -3,11 +3,10 @@
3
3
  module Lutaml
4
4
  module Uml
5
5
  class PrimitiveType < DataType
6
- attr_reader :keyword
6
+ attribute :keyword, :string, default: "primitive"
7
7
 
8
- def initialize(attributes = {})
9
- super
10
- @keyword = "primitive"
8
+ yaml do
9
+ map "keyword", to: :keyword
11
10
  end
12
11
  end
13
12
  end
@@ -3,24 +3,22 @@
3
3
  module Lutaml
4
4
  module Uml
5
5
  class Property < TopElement
6
- attr_accessor :type, # rubocop:disable Naming/MethodName
7
- :aggregation,
8
- :association,
9
- :is_derived,
10
- :lowerValue,
11
- :upperValue
6
+ attribute :type, :string
7
+ attribute :aggregation, :string
8
+ attribute :association, :string
9
+ attribute :is_derived, :boolean, default: false
10
+ attribute :visibility, :string, default: "public"
11
+ attribute :lowerValue, :string, default: "1"
12
+ attribute :upperValue, :string, default: "1"
12
13
 
13
- def initialize # rubocop:disable Lint/MissingSuper
14
- @name = nil
15
- @xmi_id = nil
16
- @xmi_uuid = nil
17
- @aggregation = nil
18
- @association = nil
19
- @namespace = nil
20
- @is_derived = false
21
- @visibility = "public"
22
- @lowerValue = "1" # rubocop:disable Naming/VariableName
23
- @upperValue = "1" # rubocop:disable Naming/VariableName
14
+ yaml do
15
+ map "type", to: :type
16
+ map "aggregation", to: :aggregation
17
+ map "association", to: :association
18
+ map "is_derived", to: :is_derived
19
+ map "visibility", to: :visibility
20
+ map "lowerValue", to: :lowerValue
21
+ map "upperValue", to: :upperValue
24
22
  end
25
23
  end
26
24
  end
@@ -3,7 +3,6 @@
3
3
  ##
4
4
  ## Behaviour metamodel
5
5
  ##
6
-
7
6
  module Lutaml
8
7
  module Uml
9
8
  class Region < TopElement
@@ -6,7 +6,15 @@
6
6
  module Lutaml
7
7
  module Uml
8
8
  class State < Vertex
9
- attr_accessor :exit, :entry, :do_activity
9
+ attribute :exit, :string
10
+ attribute :entry, :string
11
+ attribute :do_activity, :string
12
+
13
+ yaml do
14
+ map "exit", to: :exit
15
+ map "entry", to: :entry
16
+ map "do_activity", to: :do_activity
17
+ end
10
18
  end
11
19
  end
12
20
  end
@@ -3,7 +3,6 @@
3
3
  ##
4
4
  ## Behaviour metamodel
5
5
  ##
6
-
7
6
  module Lutaml
8
7
  module Uml
9
8
  class StateMachine < Behavior
@@ -2,57 +2,79 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- class TopElement
6
- include HasAttributes
7
-
8
- attr_reader :definition
9
- attr_accessor :name,
10
- :xmi_id,
11
- :xmi_uuid,
12
- :namespace,
13
- :keyword,
14
- :stereotype,
15
- :href,
16
- :visibility,
17
- :comments
18
-
19
- # rubocop:disable Rails/ActiveRecordAliases
20
- def initialize(attributes = {})
21
- @visibility = "public"
22
- @name = attributes["name"]
23
- update_attributes(attributes)
24
- end
25
- # rubocop:enable Rails/ActiveRecordAliases
5
+ class TopElement < Lutaml::Model::Serializable
6
+ attribute :name, :string
7
+ attribute :xmi_id, :string
8
+ attribute :xmi_uuid, :string
9
+ attribute :namespace, NameSpace
10
+ attribute :keyword, :string
11
+ attribute :stereotype, :string, collection: true, default: -> { [] }
12
+ attribute :href, :string
13
+ attribute :visibility, :string, default: "public"
14
+ attribute :comments, :string, collection: true
26
15
 
27
- def full_name # rubocop:disable Metrics/MethodLength
28
- if name == nil
29
- return nil
30
- end
16
+ attribute :definition, :string
17
+ attribute :full_name, :string
31
18
 
32
- the_name = name
33
- next_namespace = namespace
19
+ yaml do
20
+ map "name", to: :name
21
+ map "xmi_id", to: :xmi_id
22
+ map "xmi_uuid", to: :xmi_uuid
23
+ map "namespace", to: :namespace
24
+ map "keyword", to: :keyword
25
+ map "stereotype", to: :stereotype
26
+ map "href", to: :href
27
+ map "visibility", to: :visibility
28
+ map "comments", to: :comments
34
29
 
35
- while !next_namespace.nil?
36
- the_name = if next_namespace.name.nil?
37
- "::#{the_name}"
38
- else
39
- "#{next_namespace.name}::#{the_name}"
40
- end
41
- next_namespace = next_namespace.namespace
42
- end
30
+ map "definition", to: :definition, with: {
31
+ to: :definition_to_yaml, from: :definition_from_yaml
32
+ }
33
+ map "full_name", with: {
34
+ to: :full_name_to_yaml, from: :full_name_from_yaml
35
+ }
36
+ end
43
37
 
44
- the_name
38
+ def definition_to_yaml(model, doc)
39
+ doc["definition"] = model.definition if model.definition
45
40
  end
46
41
 
47
- def definition=(value)
48
- @definition = value
49
- .to_s
42
+ def definition_from_yaml(model, value)
43
+ model.definition = value.to_s
50
44
  .gsub(/\\}/, "}")
51
45
  .gsub(/\\{/, "{")
52
46
  .split("\n")
53
47
  .map(&:strip)
54
48
  .join("\n")
55
49
  end
50
+
51
+ def full_name_to_yaml(model, doc) # rubocop:disable Metrics/MethodLength
52
+ return model.full_name if model.full_name
53
+
54
+ # If full_name is not set, calculate it
55
+ full_name = nil
56
+ if model.name == nil
57
+ return full_name
58
+ end
59
+
60
+ full_name = model.name
61
+ next_namespace = model.namespace
62
+
63
+ while !next_namespace.nil?
64
+ full_name = if next_namespace.name.nil?
65
+ "::#{full_name}"
66
+ else
67
+ "#{next_namespace.name}::#{full_name}"
68
+ end
69
+ next_namespace = next_namespace.namespace
70
+ end
71
+
72
+ doc["full_name"] = full_name
73
+ end
74
+
75
+ def full_name_from_yaml(model, value)
76
+ model.full_name = value
77
+ end
56
78
  end
57
79
  end
58
80
  end
@@ -2,32 +2,43 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- class TopElementAttribute
6
- include HasAttributes
7
- include HasMembers
5
+ class TopElementAttribute < Lutaml::Model::Serializable
6
+ attribute :name, :string
7
+ attribute :visibility, :string, default: "public"
8
+ attribute :type, :string
9
+ attribute :id, :string
10
+ attribute :xmi_id, :string
11
+ attribute :contain, :string
12
+ attribute :static, :string
13
+ attribute :cardinality, Cardinality
14
+ attribute :keyword, :string
15
+ attribute :is_derived, :boolean, default: false
8
16
 
9
- attr_reader :definition
10
- attr_accessor :name,
11
- :visibility,
12
- :type,
13
- :id,
14
- :xmi_id,
15
- :contain,
16
- :static,
17
- :cardinality,
18
- :keyword,
19
- :is_derived
17
+ attribute :definition, :string
20
18
 
21
- # rubocop:disable Rails/ActiveRecordAliases
22
- def initialize(attributes = {})
23
- @visibility = "public"
24
- update_attributes(attributes)
19
+ yaml do
20
+ map "name", to: :name
21
+ map "visibility", to: :visibility
22
+ map "type", to: :type
23
+ map "id", to: :id
24
+ map "xmi_id", to: :xmi_id
25
+ map "contain", to: :contain
26
+ map "static", to: :static
27
+ map "cardinality", to: :cardinality
28
+ map "keyword", to: :keyword
29
+ map "is_derived", to: :is_derived
30
+
31
+ map "definition", to: :definition, with: {
32
+ to: :definition_to_yaml, from: :definition_from_yaml
33
+ }
34
+ end
35
+
36
+ def definition_to_yaml(model, doc)
37
+ doc["definition"] = model.definition if model.definition
25
38
  end
26
- # rubocop:enable Rails/ActiveRecordAliases
27
39
 
28
- def definition=(value)
29
- @definition = value
30
- .to_s
40
+ def definition_from_yaml(model, value)
41
+ model.definition = value.to_s
31
42
  .gsub(/\\}/, "}")
32
43
  .gsub(/\\{/, "{")
33
44
  .split("\n")
@@ -6,7 +6,17 @@
6
6
  module Lutaml
7
7
  module Uml
8
8
  class Transition < TopElement
9
- attr_accessor :source, :target, :guard, :effect
9
+ attribute :source, :string
10
+ attribute :target, :string
11
+ attribute :guard, :string
12
+ attribute :effect, :string
13
+
14
+ yaml do
15
+ map "source", to: :source
16
+ map "target", to: :target
17
+ map "guard", to: :guard
18
+ map "effect", to: :effect
19
+ end
10
20
  end
11
21
  end
12
22
  end
@@ -6,7 +6,11 @@
6
6
  module Lutaml
7
7
  module Uml
8
8
  class Trigger < TopElement
9
- attr_accessor :event
9
+ attribute :event, :string
10
+
11
+ yaml do
12
+ map "event", to: :event
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -2,24 +2,28 @@
2
2
 
3
3
  module Lutaml
4
4
  module Uml
5
- class Value
6
- include HasAttributes
7
- include HasMembers
5
+ class Value < Lutaml::Model::Serializable
6
+ attribute :definition, :string
7
+ attribute :name, :string
8
+ attribute :id, :string
9
+ attribute :type, :string
8
10
 
9
- attr_reader :definition
10
- attr_accessor :name,
11
- :id,
12
- :type
11
+ yaml do
12
+ map "name", to: :name
13
+ map "id", to: :id
14
+ map "type", to: :type
13
15
 
14
- # rubocop:disable Rails/ActiveRecordAliases
15
- def initialize(attributes = {})
16
- update_attributes(attributes)
16
+ map "definition", to: :definition, with: {
17
+ to: :definition_to_yaml, from: :definition_from_yaml
18
+ }
17
19
  end
18
- # rubocop:enable Rails/ActiveRecordAliases
19
20
 
20
- def definition=(value)
21
- @definition = value
22
- .to_s
21
+ def definition_to_yaml(model, doc)
22
+ doc["definition"] = model.definition if model.definition
23
+ end
24
+
25
+ def definition_from_yaml(model, value)
26
+ model.definition = value.to_s
23
27
  .gsub(/\\}/, "}")
24
28
  .gsub(/\\{/, "{")
25
29
  .split("\n")
data/lib/lutaml/uml.rb CHANGED
@@ -1,10 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "lutaml/uml/version"
3
+ require "lutaml/model"
4
+
5
+ require "lutaml/uml/has_attributes"
6
+ require "lutaml/uml/has_members"
7
+ require "lutaml/uml/namespace"
8
+ require "lutaml/uml/cardinality"
9
+ require "lutaml/uml/fidelity"
10
+ require "lutaml/uml/top_element"
11
+ require "lutaml/uml/top_element_attribute"
12
+ require "lutaml/uml/value"
13
+ require "lutaml/uml/action"
14
+ require "lutaml/uml/classifier"
15
+ require "lutaml/uml/dependency"
16
+ require "lutaml/uml/association"
17
+ require "lutaml/uml/constraint"
18
+ require "lutaml/uml/operation"
19
+ require "lutaml/uml/class"
20
+ require "lutaml/uml/data_type"
21
+ require "lutaml/uml/enum"
22
+ require "lutaml/uml/diagram"
23
+ require "lutaml/uml/package"
24
+ require "lutaml/uml/primitive_type"
25
+ require "lutaml/uml/group"
26
+ require "lutaml/uml/connector"
27
+ require "lutaml/uml/connector_end"
28
+ require "lutaml/uml/behavior"
29
+ require "lutaml/uml/activity"
30
+ require "lutaml/uml/vertex"
31
+ require "lutaml/uml/state"
32
+ require "lutaml/uml/final_state"
33
+ require "lutaml/uml/property"
34
+ require "lutaml/uml/port"
35
+ require "lutaml/uml/document"
36
+
4
37
  require "lutaml/uml/parsers/dsl"
5
38
  require "lutaml/uml/parsers/yaml"
6
39
  require "lutaml/uml/parsers/attribute"
7
- require "lutaml/uml/formatter"
40
+ require "lutaml/formatter"
41
+ require "lutaml/formatter/graphviz"
42
+
43
+ Dir.glob(File.expand_path("./uml/**/*.rb", __dir__)).sort.each do |file|
44
+ require file
45
+ end
8
46
 
9
47
  module Lutaml
10
48
  module Uml
@@ -1,3 +1,3 @@
1
1
  module Lutaml
2
- VERSION = "0.9.39".freeze
2
+ VERSION = "0.9.40".freeze
3
3
  end
@@ -46,7 +46,7 @@ module Lutaml
46
46
  end
47
47
 
48
48
  def subtype_of
49
- find_subtype_of(@model.id)
49
+ find_subtype_of_from_owned_attribute_type(@model.id)
50
50
  end
51
51
  end
52
52
  end
@@ -186,7 +186,8 @@ module Lutaml
186
186
  end
187
187
 
188
188
  def subtype_of
189
- find_subtype_of(@model.id)
189
+ find_subtype_of_from_generalization(@model.id) ||
190
+ find_subtype_of_from_owned_attribute_type(@model.id)
190
191
  end
191
192
 
192
193
  def has_guidance?
@@ -297,7 +297,7 @@ module Lutaml
297
297
  @upper_level_cache[klass_id]
298
298
  end
299
299
 
300
- def find_subtype_of(id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
300
+ def find_subtype_of_from_owned_attribute_type(id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
301
301
  @pkg_elements_owned_attributes ||= all_packaged_elements.map do |e|
302
302
  {
303
303
  name: e.name,
@@ -306,7 +306,6 @@ module Lutaml
306
306
  end || [],
307
307
  }
308
308
  end
309
-
310
309
  result = @pkg_elements_owned_attributes.find do |e|
311
310
  e[:idrefs].include?(id)
312
311
  end
@@ -314,6 +313,25 @@ module Lutaml
314
313
  result[:name] if result
315
314
  end
316
315
 
316
+ def find_subtype_of_from_generalization(id) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
317
+ matched_element = @xmi_root_model.extension.elements.element
318
+ .find { |e| e.idref == id }
319
+
320
+ return if !matched_element || !matched_element.links
321
+
322
+ matched_generalization = nil
323
+ matched_element.links.each do |link|
324
+ matched_generalization = link&.generalization&.find do |g|
325
+ g.start == id
326
+ end
327
+ break if matched_generalization
328
+ end
329
+
330
+ return if matched_generalization&.end.nil?
331
+
332
+ lookup_entity_name(matched_generalization.end)
333
+ end
334
+
317
335
  # Build cache once for all packaged elements
318
336
  def build_upper_level_cache
319
337
  @upper_level_cache = {}