lutaml 0.10.4 → 0.10.6

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +10 -0
  4. data/.rubocop_todo.yml +218 -94
  5. data/TODO.cleanups/01-resolve-production-todos.md +65 -0
  6. data/TODO.cleanups/02-reduce-metrics-offenses.md +37 -0
  7. data/TODO.cleanups/03-reduce-rspec-multiple-expectations.md +54 -0
  8. data/TODO.cleanups/04-reduce-rspec-example-length.md +45 -0
  9. data/TODO.cleanups/05-replace-marshal-load.md +37 -0
  10. data/TODO.cleanups/06-replace-eval-in-tests.md +41 -0
  11. data/TODO.cleanups/07-fix-lint-offenses.md +74 -0
  12. data/TODO.cleanups/08-reduce-memoized-helpers-and-nesting.md +43 -0
  13. data/TODO.cleanups/09-reduce-verified-doubles-and-rspec-style.md +57 -0
  14. data/TODO.cleanups/10-split-large-files.md +47 -0
  15. data/bin/console +0 -1
  16. data/exe/lutaml +1 -0
  17. data/lib/lutaml/cli/element_identifier.rb +3 -6
  18. data/lib/lutaml/cli/interactive_shell/bookmark_commands.rb +88 -0
  19. data/lib/lutaml/cli/interactive_shell/command_base.rb +32 -0
  20. data/lib/lutaml/cli/interactive_shell/export_handler.rb +67 -0
  21. data/lib/lutaml/cli/interactive_shell/help_display.rb +114 -0
  22. data/lib/lutaml/cli/interactive_shell/navigation_commands.rb +135 -0
  23. data/lib/lutaml/cli/interactive_shell/query_commands.rb +185 -0
  24. data/lib/lutaml/cli/interactive_shell.rb +116 -802
  25. data/lib/lutaml/cli/uml/build_command.rb +5 -5
  26. data/lib/lutaml/cli/uml/verify_command.rb +0 -1
  27. data/lib/lutaml/converter/xmi_to_uml.rb +3 -153
  28. data/lib/lutaml/converter/xmi_to_uml_generalization.rb +193 -0
  29. data/lib/lutaml/formatter/graphviz.rb +1 -2
  30. data/lib/lutaml/qea/database.rb +1 -47
  31. data/lib/lutaml/qea/factory/association_builder.rb +188 -0
  32. data/lib/lutaml/qea/factory/base_transformer.rb +0 -1
  33. data/lib/lutaml/qea/factory/class_transformer.rb +40 -590
  34. data/lib/lutaml/qea/factory/diagram_transformer.rb +0 -3
  35. data/lib/lutaml/qea/factory/generalization_builder.rb +211 -0
  36. data/lib/lutaml/qea/factory/package_transformer.rb +1 -2
  37. data/lib/lutaml/qea/factory/stereotype_loader.rb +34 -0
  38. data/lib/lutaml/qea/lookup_indexes.rb +54 -0
  39. data/lib/lutaml/qea/models/ea_datatype.rb +0 -2
  40. data/lib/lutaml/qea/validation/validation_engine.rb +0 -2
  41. data/lib/lutaml/uml/has_members.rb +0 -1
  42. data/lib/lutaml/uml/inheritance_walker.rb +92 -0
  43. data/lib/lutaml/uml/model_helpers.rb +129 -0
  44. data/lib/lutaml/uml/node/attribute.rb +3 -1
  45. data/lib/lutaml/uml/node/class_node.rb +3 -3
  46. data/lib/lutaml/uml/operation.rb +2 -0
  47. data/lib/lutaml/uml_repository/class_lookup_index.rb +40 -0
  48. data/lib/lutaml/uml_repository/exporters/markdown/class_page_builder.rb +179 -0
  49. data/lib/lutaml/uml_repository/exporters/markdown/formatting.rb +36 -0
  50. data/lib/lutaml/uml_repository/exporters/markdown/index_page_builder.rb +73 -0
  51. data/lib/lutaml/uml_repository/exporters/markdown/link_resolver.rb +40 -0
  52. data/lib/lutaml/uml_repository/exporters/markdown/package_page_builder.rb +107 -0
  53. data/lib/lutaml/uml_repository/exporters/markdown_exporter.rb +26 -538
  54. data/lib/lutaml/uml_repository/index_builder.rb +3 -271
  55. data/lib/lutaml/uml_repository/index_builders/association_index.rb +141 -0
  56. data/lib/lutaml/uml_repository/index_builders/class_index.rb +94 -0
  57. data/lib/lutaml/uml_repository/index_builders/package_index.rb +57 -0
  58. data/lib/lutaml/uml_repository/package_exporter.rb +10 -20
  59. data/lib/lutaml/uml_repository/package_loader.rb +37 -17
  60. data/lib/lutaml/uml_repository/repository/deprecated.rb +39 -0
  61. data/lib/lutaml/uml_repository/repository/loader.rb +112 -0
  62. data/lib/lutaml/uml_repository/repository.rb +7 -57
  63. data/lib/lutaml/uml_repository/static_site/association_serialization.rb +142 -0
  64. data/lib/lutaml/uml_repository/static_site/configuration.rb +0 -2
  65. data/lib/lutaml/uml_repository/static_site/data_transformer.rb +52 -873
  66. data/lib/lutaml/uml_repository/static_site/generator.rb +29 -8
  67. data/lib/lutaml/uml_repository/static_site/search_index_builder.rb +1 -4
  68. data/lib/lutaml/uml_repository/static_site/serializers/attribute_serializer.rb +78 -0
  69. data/lib/lutaml/uml_repository/static_site/serializers/class_serializer.rb +124 -0
  70. data/lib/lutaml/uml_repository/static_site/serializers/diagram_serializer.rb +60 -0
  71. data/lib/lutaml/uml_repository/static_site/serializers/inheritance_resolver.rb +258 -0
  72. data/lib/lutaml/uml_repository/static_site/serializers/metadata_builder.rb +48 -0
  73. data/lib/lutaml/uml_repository/static_site/serializers/operation_serializer.rb +57 -0
  74. data/lib/lutaml/uml_repository/static_site/serializers/package_serializer.rb +94 -0
  75. data/lib/lutaml/uml_repository/static_site/serializers/package_tree_builder.rb +93 -0
  76. data/lib/lutaml/version.rb +1 -1
  77. data/lib/lutaml/xmi/liquid_drops/association_drop.rb +13 -35
  78. data/lib/lutaml/xmi/liquid_drops/attribute_drop.rb +12 -18
  79. data/lib/lutaml/xmi/liquid_drops/cardinality_drop.rb +14 -6
  80. data/lib/lutaml/xmi/liquid_drops/connector_drop.rb +0 -3
  81. data/lib/lutaml/xmi/liquid_drops/constraint_drop.rb +1 -3
  82. data/lib/lutaml/xmi/liquid_drops/data_type_drop.rb +13 -70
  83. data/lib/lutaml/xmi/liquid_drops/dependency_drop.rb +2 -5
  84. data/lib/lutaml/xmi/liquid_drops/diagram_drop.rb +5 -11
  85. data/lib/lutaml/xmi/liquid_drops/enum_drop.rb +8 -16
  86. data/lib/lutaml/xmi/liquid_drops/enum_owned_literal_drop.rb +3 -9
  87. data/lib/lutaml/xmi/liquid_drops/generalization_attribute_drop.rb +11 -13
  88. data/lib/lutaml/xmi/liquid_drops/generalization_drop.rb +27 -85
  89. data/lib/lutaml/xmi/liquid_drops/klass_drop.rb +39 -91
  90. data/lib/lutaml/xmi/liquid_drops/operation_drop.rb +3 -9
  91. data/lib/lutaml/xmi/liquid_drops/package_drop.rb +16 -44
  92. data/lib/lutaml/xmi/liquid_drops/root_drop.rb +3 -11
  93. data/lib/lutaml/xmi/liquid_drops/source_target_drop.rb +2 -5
  94. data/lib/lutaml/xmi/parsers/xmi_base.rb +2 -749
  95. data/lib/lutaml/xmi/parsers/xmi_class_members.rb +45 -0
  96. data/lib/lutaml/xmi/parsers/xmi_connector.rb +251 -0
  97. data/lib/lutaml/xmi/parsers/xml.rb +7 -120
  98. data/lib/lutaml/xmi/xmi_lookup_service.rb +42 -0
  99. data/lib/lutaml.rb +0 -1
  100. metadata +48 -21
  101. data/lib/lutaml/cli/commands/base_command.rb +0 -118
  102. data/lib/lutaml/command_line.rb +0 -272
  103. data/lib/lutaml/sysml/allocate.rb +0 -9
  104. data/lib/lutaml/sysml/allocated.rb +0 -9
  105. data/lib/lutaml/sysml/binding_connector.rb +0 -9
  106. data/lib/lutaml/sysml/block.rb +0 -32
  107. data/lib/lutaml/sysml/constraint_block.rb +0 -14
  108. data/lib/lutaml/sysml/copy.rb +0 -8
  109. data/lib/lutaml/sysml/derive_requirement.rb +0 -9
  110. data/lib/lutaml/sysml/nested_connector_end.rb +0 -13
  111. data/lib/lutaml/sysml/refine.rb +0 -9
  112. data/lib/lutaml/sysml/requirement.rb +0 -44
  113. data/lib/lutaml/sysml/requirement_related.rb +0 -9
  114. data/lib/lutaml/sysml/satisfy.rb +0 -9
  115. data/lib/lutaml/sysml/test_case.rb +0 -25
  116. data/lib/lutaml/sysml/trace.rb +0 -9
  117. data/lib/lutaml/sysml/verify.rb +0 -8
  118. data/lib/lutaml/sysml/xmi_file.rb +0 -486
  119. data/lib/lutaml/sysml.rb +0 -11
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_base"
4
+ require_relative "../enhanced_formatter"
5
+
6
+ module Lutaml
7
+ module Cli
8
+ class InteractiveShell
9
+ class HelpDisplay < CommandBase
10
+ def display_welcome
11
+ puts OutputFormatter.colorize(
12
+ "╔═══════════════════════════════════════╗", :cyan
13
+ )
14
+ puts OutputFormatter.colorize(
15
+ "║ LutaML Interactive Shell (REPL) ║", :cyan
16
+ )
17
+ puts OutputFormatter.colorize(
18
+ "╚═══════════════════════════════════════╝", :cyan
19
+ )
20
+ puts ""
21
+ puts "Type 'help' for available commands, 'exit' to quit"
22
+ puts ""
23
+
24
+ stats = repository.statistics
25
+ puts "Repository loaded:"
26
+ puts " #{stats[:total_packages]} packages, " \
27
+ "#{stats[:total_classes]} classes"
28
+ puts ""
29
+ end
30
+
31
+ def cmd_help(args)
32
+ if args.empty?
33
+ display_general_help
34
+ else
35
+ display_command_help(args[0])
36
+ end
37
+ end
38
+
39
+ def cmd_history(_args)
40
+ history = Readline::HISTORY.to_a.last(20)
41
+ history.each_with_index do |line, i|
42
+ puts "#{i + 1}. #{line}"
43
+ end
44
+ end
45
+
46
+ def cmd_clear(_args)
47
+ print "\e[2J\e[H"
48
+ end
49
+
50
+ def cmd_config(_args)
51
+ puts OutputFormatter.colorize("Current Configuration:", :cyan)
52
+ config.each do |key, value|
53
+ puts " #{key}: #{value}"
54
+ end
55
+ end
56
+
57
+ def cmd_stats(_args)
58
+ stats = repository.statistics
59
+
60
+ if config[:icons]
61
+ puts EnhancedFormatter.format_stats_enhanced(stats)
62
+ else
63
+ puts OutputFormatter.format_stats(stats, detailed: false)
64
+ end
65
+ end
66
+
67
+ def display_general_help
68
+ puts OutputFormatter.colorize("Available Commands:", :cyan)
69
+ puts ""
70
+
71
+ puts OutputFormatter.colorize("Navigation:", :yellow)
72
+ puts " cd PATH Change to package path"
73
+ puts " pwd Print current path"
74
+ puts " ls [PATH] List packages"
75
+ puts " tree [PATH] Show package tree"
76
+ puts " up Go to parent package"
77
+ puts " root Go to ModelRoot"
78
+ puts " back Go to previous location"
79
+ puts ""
80
+
81
+ puts OutputFormatter.colorize("Query:", :yellow)
82
+ puts " find CLASS Find class (fuzzy search)"
83
+ puts " show class QNAME Show class details"
84
+ puts " show package PATH Show package details"
85
+ puts " show NUMBER Show numbered result"
86
+ puts " search QUERY Full-text search"
87
+ puts " ? QUERY Alias for search"
88
+ puts ""
89
+
90
+ puts OutputFormatter.colorize("Bookmarks:", :yellow)
91
+ puts " bookmark add NAME Bookmark current location"
92
+ puts " bookmark list List bookmarks"
93
+ puts " bookmark go NAME Jump to bookmark"
94
+ puts " bookmark rm NAME Remove bookmark"
95
+ puts " bm NAME Quick jump"
96
+ puts ""
97
+
98
+ puts OutputFormatter.colorize("Utilities:", :yellow)
99
+ puts " help [COMMAND] Show help"
100
+ puts " history Show command history"
101
+ puts " clear Clear screen"
102
+ puts " config Show configuration"
103
+ puts " stats Show statistics"
104
+ puts " exit, quit, q Exit shell"
105
+ end
106
+
107
+ def display_command_help(command)
108
+ puts "Help for '#{command}' not yet implemented"
109
+ puts "Use 'help' for general help"
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_base"
4
+ require_relative "../enhanced_formatter"
5
+
6
+ module Lutaml
7
+ module Cli
8
+ class InteractiveShell
9
+ class NavigationCommands < CommandBase
10
+ def cmd_cd(args)
11
+ if args.empty?
12
+ puts OutputFormatter.warning("Usage: cd PATH")
13
+ return
14
+ end
15
+
16
+ path = resolve_path(args[0])
17
+ pkg = repository.find_package(path)
18
+
19
+ if pkg
20
+ push_path_history
21
+ self.current_path = path
22
+ puts "Changed to: #{path}"
23
+ else
24
+ puts OutputFormatter.error("Package not found: #{path}")
25
+ end
26
+ end
27
+
28
+ def cmd_pwd(_args)
29
+ puts current_path
30
+ end
31
+
32
+ def cmd_ls(args)
33
+ path = args.empty? ? current_path : resolve_path(args[0])
34
+ recursive = args.include?("-r") || args.include?("--recursive")
35
+
36
+ packages = repository.list_packages(path, recursive: recursive)
37
+
38
+ if packages.empty?
39
+ puts OutputFormatter.warning("No packages found at #{path}")
40
+ else
41
+ packages.each do |pkg|
42
+ icon = config[:icons] ? "#{EnhancedFormatter::ICONS[:package]} " : ""
43
+ puts "#{icon}#{pkg.name}"
44
+ end
45
+ puts ""
46
+ puts "Total: #{packages.size} package(s)"
47
+ end
48
+ end
49
+
50
+ def cmd_tree(args)
51
+ path = args.empty? ? current_path : resolve_path(args[0])
52
+
53
+ max_depth = nil
54
+ args.each_with_index do |arg, i|
55
+ max_depth = args[i + 1].to_i if arg == "-d" && args[i + 1]
56
+ end
57
+
58
+ tree_data = repository.package_tree(path, max_depth: max_depth)
59
+
60
+ unless tree_data
61
+ puts OutputFormatter.error("Package not found: #{path}")
62
+ return
63
+ end
64
+
65
+ if config[:icons]
66
+ puts EnhancedFormatter.format_tree_with_icons(tree_data, config)
67
+ else
68
+ puts OutputFormatter.format_tree(tree_data)
69
+ end
70
+ end
71
+
72
+ def cmd_up(_args)
73
+ if current_path == "ModelRoot"
74
+ puts OutputFormatter.warning("Already at root")
75
+ return
76
+ end
77
+
78
+ parts = current_path.split("::")
79
+ parts.pop
80
+ new_path = parts.empty? ? "ModelRoot" : parts.join("::")
81
+
82
+ push_path_history
83
+ self.current_path = new_path
84
+ puts "Changed to: #{current_path}"
85
+ end
86
+
87
+ def cmd_root(_args)
88
+ if current_path == "ModelRoot"
89
+ puts "Already at root"
90
+ else
91
+ push_path_history
92
+ self.current_path = "ModelRoot"
93
+ puts "Changed to: ModelRoot"
94
+ end
95
+ end
96
+
97
+ def cmd_back(_args)
98
+ if path_history.size > 1
99
+ path_history.pop
100
+ self.current_path = path_history.last
101
+ puts "Changed to: #{current_path}"
102
+ else
103
+ puts OutputFormatter.warning("No previous location")
104
+ end
105
+ end
106
+
107
+ def resolve_path(path)
108
+ return path if path.start_with?("ModelRoot")
109
+ return current_path if path == "."
110
+ return "ModelRoot" if path == "/"
111
+
112
+ if path.start_with?("../")
113
+ parts = current_path.split("::")
114
+ path.scan("../").each { parts.pop }
115
+ remaining = path.gsub(/^(\.\.\/)+/, "")
116
+ new_path = parts + remaining.split("/")
117
+ new_path.join("::")
118
+ elsif path.start_with?("./")
119
+ "#{current_path}::#{path[2..]}"
120
+ else
121
+ current_path == "ModelRoot" ? path : "#{current_path}::#{path}"
122
+ end
123
+ end
124
+
125
+ private
126
+
127
+ def push_path_history
128
+ return if path_history.last == current_path
129
+
130
+ path_history << current_path
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "command_base"
4
+ require_relative "../enhanced_formatter"
5
+
6
+ module Lutaml
7
+ module Cli
8
+ class InteractiveShell
9
+ class QueryCommands < CommandBase
10
+ def cmd_find(args)
11
+ if args.empty?
12
+ puts OutputFormatter.warning("Usage: find CLASS_NAME")
13
+ return
14
+ end
15
+
16
+ query = args.join(" ")
17
+ results = repository.search(query, types: [:class])
18
+
19
+ if results[:class].empty?
20
+ puts OutputFormatter.warning("No classes found matching '#{query}'")
21
+ else
22
+ self.last_results = results[:class]
23
+
24
+ puts OutputFormatter.colorize(
25
+ "Found #{last_results.size} class(es):", :cyan
26
+ )
27
+ last_results.each_with_index do |qname, i|
28
+ puts " #{i + 1}. #{qname}"
29
+ end
30
+ puts ""
31
+ puts "Use 'show NUMBER' to view details"
32
+ end
33
+ end
34
+
35
+ def cmd_show(args)
36
+ if args.empty?
37
+ puts OutputFormatter.warning(
38
+ "Usage: show class QNAME | show package PATH | show NUMBER",
39
+ )
40
+ return
41
+ end
42
+
43
+ subcommand = args[0].downcase
44
+
45
+ case subcommand
46
+ when "class"
47
+ show_class(args[1..].join(" "))
48
+ when "package"
49
+ show_package(args[1..].join(" "))
50
+ when /^\d+$/
51
+ show_numbered_result(subcommand.to_i)
52
+ else
53
+ show_class(args.join(" "))
54
+ end
55
+ end
56
+
57
+ def cmd_search(args)
58
+ if args.empty?
59
+ puts OutputFormatter.warning("Usage: search QUERY")
60
+ return
61
+ end
62
+
63
+ query = args.join(" ")
64
+ results = repository.search(query)
65
+
66
+ if results.values.all?(&:empty?)
67
+ puts OutputFormatter.warning("No results found for '#{query}'")
68
+ else
69
+ display_search_results(results)
70
+ end
71
+ end
72
+
73
+ def cmd_results(_args)
74
+ if last_results.nil? || last_results.empty?
75
+ puts OutputFormatter.warning("No previous results")
76
+ else
77
+ puts OutputFormatter.colorize(
78
+ "Last results (#{last_results.size}):", :cyan
79
+ )
80
+ last_results.each_with_index do |item, i|
81
+ puts " #{i + 1}. #{item}"
82
+ end
83
+ end
84
+ end
85
+
86
+ def show_class(qname)
87
+ cls = repository.find_class(qname)
88
+
89
+ unless cls
90
+ puts OutputFormatter.error("Class not found: #{qname}")
91
+ return
92
+ end
93
+
94
+ if config[:icons]
95
+ puts EnhancedFormatter.format_class_details_enhanced(cls)
96
+ else
97
+ puts OutputFormatter.colorize("Class: #{qname}", :cyan)
98
+ puts "=" * 50
99
+ puts ""
100
+ puts "Name: #{cls.name}"
101
+
102
+ if cls.respond_to?(:attributes) && cls.attributes && !cls.attributes.empty?
103
+ puts ""
104
+ puts OutputFormatter.colorize("Attributes:", :yellow)
105
+ cls.attributes.each do |attr|
106
+ puts " - #{attr.name}: #{attr.type}"
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ def show_package(path)
113
+ nav = shell.instance_variable_get(:@navigation)
114
+ path = nav.resolve_path(path)
115
+ pkg = repository.find_package(path)
116
+
117
+ unless pkg
118
+ puts OutputFormatter.error("Package not found: #{path}")
119
+ return
120
+ end
121
+
122
+ puts OutputFormatter.colorize("Package: #{path}", :cyan)
123
+ puts "=" * 50
124
+ puts ""
125
+ puts "Name: #{pkg.name}"
126
+ puts ""
127
+
128
+ classes = repository.classes_in_package(path)
129
+ puts OutputFormatter.colorize("Classes (#{classes.size}):", :yellow)
130
+ classes.each do |cls|
131
+ icon = config[:icons] ? "#{EnhancedFormatter::ICONS[:class]} " : ""
132
+ puts " #{icon}#{cls.name}"
133
+ end
134
+ end
135
+
136
+ def show_numbered_result(number)
137
+ if last_results.nil? || last_results.empty?
138
+ puts OutputFormatter.warning("No previous results")
139
+ return
140
+ end
141
+
142
+ index = number - 1
143
+ if index.negative? || index >= last_results.size
144
+ puts OutputFormatter.error("Invalid result number: #{number}")
145
+ return
146
+ end
147
+
148
+ show_class(last_results[index])
149
+ end
150
+
151
+ def display_search_results(results)
152
+ results.each do |type, items|
153
+ next if items.empty?
154
+
155
+ puts ""
156
+ puts OutputFormatter.colorize(
157
+ "#{type.to_s.capitalize} Results (#{items.size}):", :cyan
158
+ )
159
+
160
+ case type
161
+ when :class
162
+ self.last_results = items
163
+ items.each_with_index do |qname, i|
164
+ icon = config[:icons] ? "#{EnhancedFormatter::ICONS[:class]} " : ""
165
+ puts " #{i + 1}. #{icon}#{qname}"
166
+ end
167
+ puts ""
168
+ puts "Use 'show NUMBER' to view details"
169
+ when :attribute
170
+ items.each do |item|
171
+ puts " - #{item[:class_name]}::#{item[:attribute_name]} : " \
172
+ "#{item[:type]}"
173
+ end
174
+ when :association
175
+ items.each do |item|
176
+ icon = config[:icons] ? "#{EnhancedFormatter::ICONS[:association]} " : ""
177
+ puts " #{icon}#{item[:source]} → #{item[:target]}"
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end