mxrb 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.de-DE.md +108 -0
- data/README.md +172 -0
- data/README.pt-BR.md +109 -0
- data/bin/mxrb +1613 -0
- data/docs/README.md +10 -0
- data/docs/de-DE/README.md +24 -0
- data/docs/de-DE/architectural-patterns.md +26 -0
- data/docs/de-DE/architectural-standard.md +48 -0
- data/docs/de-DE/architecture.md +76 -0
- data/docs/de-DE/compiler.md +162 -0
- data/docs/de-DE/conventions.md +19 -0
- data/docs/de-DE/design-system.md +52 -0
- data/docs/de-DE/entity-dsl.md +53 -0
- data/docs/de-DE/native-runtime-quality-report.md +74 -0
- data/docs/de-DE/oql-sql.md +211 -0
- data/docs/de-DE/platform-api-integration.md +36 -0
- data/docs/de-DE/platform-operations.md +243 -0
- data/docs/de-DE/project-structure.md +32 -0
- data/docs/de-DE/ruby-first-roadmap.md +116 -0
- data/docs/de-DE/scaffolds.md +59 -0
- data/docs/de-DE/semantic-refactoring.md +56 -0
- data/docs/de-DE/team-server.md +33 -0
- data/docs/de-DE/validation-matrix.md +64 -0
- data/docs/de-DE/vetclinic-acceptance.md +24 -0
- data/docs/de-DE/writing.md +138 -0
- data/docs/en-US/README.md +24 -0
- data/docs/en-US/architectural-patterns.md +151 -0
- data/docs/en-US/architectural-standard.md +89 -0
- data/docs/en-US/architecture.md +170 -0
- data/docs/en-US/compiler.md +157 -0
- data/docs/en-US/conventions.md +82 -0
- data/docs/en-US/design-system.md +163 -0
- data/docs/en-US/entity-dsl.md +53 -0
- data/docs/en-US/native-runtime-quality-report.md +73 -0
- data/docs/en-US/oql-sql.md +201 -0
- data/docs/en-US/platform-api-integration.md +36 -0
- data/docs/en-US/platform-operations.md +244 -0
- data/docs/en-US/project-structure.md +49 -0
- data/docs/en-US/ruby-first-roadmap.md +186 -0
- data/docs/en-US/scaffolds.md +57 -0
- data/docs/en-US/semantic-refactoring.md +198 -0
- data/docs/en-US/team-server.md +32 -0
- data/docs/en-US/validation-matrix.md +257 -0
- data/docs/en-US/vetclinic-acceptance.md +23 -0
- data/docs/en-US/writing.md +655 -0
- data/docs/pt-BR/README.md +24 -0
- data/docs/pt-BR/architectural-patterns.md +25 -0
- data/docs/pt-BR/architectural-standard.md +533 -0
- data/docs/pt-BR/architecture.md +300 -0
- data/docs/pt-BR/compiler.md +162 -0
- data/docs/pt-BR/conventions.md +19 -0
- data/docs/pt-BR/design-system.md +65 -0
- data/docs/pt-BR/entity-dsl.md +116 -0
- data/docs/pt-BR/native-runtime-quality-report.md +73 -0
- data/docs/pt-BR/oql-sql.md +208 -0
- data/docs/pt-BR/platform-api-integration.md +36 -0
- data/docs/pt-BR/platform-operations.md +260 -0
- data/docs/pt-BR/project-structure.md +32 -0
- data/docs/pt-BR/ruby-first-roadmap.md +239 -0
- data/docs/pt-BR/scaffolds.md +104 -0
- data/docs/pt-BR/semantic-refactoring.md +55 -0
- data/docs/pt-BR/team-server.md +59 -0
- data/docs/pt-BR/validation-matrix.md +86 -0
- data/docs/pt-BR/vetclinic-acceptance.md +50 -0
- data/docs/pt-BR/writing.md +177 -0
- data/examples/sudoku_evaluation.rb +14 -0
- data/examples/sudoku_functional_test.rb +28 -0
- data/lib/mxrb/architecture/graph.rb +124 -0
- data/lib/mxrb/architecture/validator.rb +98 -0
- data/lib/mxrb/benchmark.rb +33 -0
- data/lib/mxrb/compare.rb +390 -0
- data/lib/mxrb/compiler/adapter.rb +96 -0
- data/lib/mxrb/compiler/artifact_document_compiler.rb +102 -0
- data/lib/mxrb/compiler/artifact_materializer.rb +53 -0
- data/lib/mxrb/compiler/client_model_materializer.rb +42 -0
- data/lib/mxrb/compiler/code_action_document_compiler.rb +64 -0
- data/lib/mxrb/compiler/code_action_materializer.rb +35 -0
- data/lib/mxrb/compiler/code_action_type_compiler.rb +32 -0
- data/lib/mxrb/compiler/combo_box_bundle_compiler.rb +314 -0
- data/lib/mxrb/compiler/compatibility_analyzer.rb +169 -0
- data/lib/mxrb/compiler/constants_materializer.rb +111 -0
- data/lib/mxrb/compiler/data_grid_bundle_compiler.rb +290 -0
- data/lib/mxrb/compiler/database_connector_action_compiler.rb +280 -0
- data/lib/mxrb/compiler/deployment_asset_copier.rb +60 -0
- data/lib/mxrb/compiler/deployment_bootstrapper.rb +208 -0
- data/lib/mxrb/compiler/deployment_materializer.rb +43 -0
- data/lib/mxrb/compiler/deployment_metadata.rb +64 -0
- data/lib/mxrb/compiler/domain_document_compiler.rb +153 -0
- data/lib/mxrb/compiler/domain_model_materializer.rb +35 -0
- data/lib/mxrb/compiler/domain_security_compiler.rb +82 -0
- data/lib/mxrb/compiler/gallery_bundle_compiler.rb +190 -0
- data/lib/mxrb/compiler/generic_widget_bundle_compiler.rb +281 -0
- data/lib/mxrb/compiler/image_bundle_compiler.rb +216 -0
- data/lib/mxrb/compiler/java_proxy_generator.rb +509 -0
- data/lib/mxrb/compiler/legacy_data_grid_compiler.rb +267 -0
- data/lib/mxrb/compiler/legacy_page_builder.rb +287 -0
- data/lib/mxrb/compiler/mda.rb +99 -0
- data/lib/mxrb/compiler/microflow_document_compiler.rb +85 -0
- data/lib/mxrb/compiler/microflow_materializer.rb +48 -0
- data/lib/mxrb/compiler/microflow_node_compiler.rb +250 -0
- data/lib/mxrb/compiler/model_package.rb +116 -0
- data/lib/mxrb/compiler/model_values.rb +67 -0
- data/lib/mxrb/compiler/nanoflow_program_compiler.rb +483 -0
- data/lib/mxrb/compiler/navigation_document_compiler.rb +93 -0
- data/lib/mxrb/compiler/packager.rb +100 -0
- data/lib/mxrb/compiler/page_bundle_builder.rb +56 -0
- data/lib/mxrb/compiler/page_bundle_compiler.rb +2004 -0
- data/lib/mxrb/compiler/page_document_compiler.rb +77 -0
- data/lib/mxrb/compiler/portable_packager.rb +356 -0
- data/lib/mxrb/compiler/project_jar_archive.rb +84 -0
- data/lib/mxrb/compiler/project_jar_builder.rb +121 -0
- data/lib/mxrb/compiler/project_materializer.rb +139 -0
- data/lib/mxrb/compiler/project_model_orderer.rb +52 -0
- data/lib/mxrb/compiler/runtime_data_types.rb +31 -0
- data/lib/mxrb/compiler/runtime_model_schema.rb +90 -0
- data/lib/mxrb/compiler/schemas/runtime-10.24.0.73019.json +1052 -0
- data/lib/mxrb/compiler/schemas/runtime-11.json +1215 -0
- data/lib/mxrb/compiler/schemas/runtime-6.10.8.json +1148 -0
- data/lib/mxrb/compiler/schemas/runtime-7.17.0.json +1144 -0
- data/lib/mxrb/compiler/schemas/runtime-7.5.0.json +1215 -0
- data/lib/mxrb/compiler/schemas/runtime-9.6.1.29396.json +868 -0
- data/lib/mxrb/compiler/schemas/system-model-10.24.0.73019.b64 +1135 -0
- data/lib/mxrb/compiler/schemas/system-model-11.12.1.b64 +815 -0
- data/lib/mxrb/compiler/schemas/system-model-6.10.8.b64 +497 -0
- data/lib/mxrb/compiler/schemas/system-model-7.17.0.b64 +519 -0
- data/lib/mxrb/compiler/schemas/system-model-7.5.0.b64 +504 -0
- data/lib/mxrb/compiler/schemas/system-model-9.6.1.29396.b64 +816 -0
- data/lib/mxrb/compiler/security_materializer.rb +104 -0
- data/lib/mxrb/compiler/settings_document_compiler.rb +45 -0
- data/lib/mxrb/compiler/settings_materializer.rb +25 -0
- data/lib/mxrb/compiler/source_model.rb +128 -0
- data/lib/mxrb/compiler/system_model_seed.rb +88 -0
- data/lib/mxrb/compiler/system_queue_materializer.rb +54 -0
- data/lib/mxrb/compiler/system_text_materializer.rb +49 -0
- data/lib/mxrb/compiler/translation_materializer.rb +95 -0
- data/lib/mxrb/compiler/web_bundle_builder.rb +155 -0
- data/lib/mxrb/compiler/web_list_data_source.rb +139 -0
- data/lib/mxrb/compiler/web_operation_compiler.rb +614 -0
- data/lib/mxrb/compiler/web_shell_materializer.rb +194 -0
- data/lib/mxrb/compiler/widget_package_extractor.rb +63 -0
- data/lib/mxrb/doctor.rb +116 -0
- data/lib/mxrb/dsl/builder.rb +1636 -0
- data/lib/mxrb/errors.rb +18 -0
- data/lib/mxrb/evaluation.rb +131 -0
- data/lib/mxrb/exporter.rb +1716 -0
- data/lib/mxrb/frontend/migrator.rb +775 -0
- data/lib/mxrb/functional.rb +307 -0
- data/lib/mxrb/github/annotator.rb +161 -0
- data/lib/mxrb/initializer.rb +257 -0
- data/lib/mxrb/integrity/validator.rb +136 -0
- data/lib/mxrb/io/bson_codec.rb +145 -0
- data/lib/mxrb/io/mpr_file.rb +558 -0
- data/lib/mxrb/io/mxunit_codec.rb +42 -0
- data/lib/mxrb/marketplace.rb +380 -0
- data/lib/mxrb/model/association.rb +98 -0
- data/lib/mxrb/model/attribute.rb +100 -0
- data/lib/mxrb/model/connector.rb +17 -0
- data/lib/mxrb/model/design_materializer.rb +133 -0
- data/lib/mxrb/model/design_migration.rb +126 -0
- data/lib/mxrb/model/design_system.rb +111 -0
- data/lib/mxrb/model/domain_model.rb +51 -0
- data/lib/mxrb/model/entity.rb +180 -0
- data/lib/mxrb/model/menu.rb +38 -0
- data/lib/mxrb/model/microflow.rb +100 -0
- data/lib/mxrb/model/module.rb +142 -0
- data/lib/mxrb/model/navigation.rb +127 -0
- data/lib/mxrb/model/page.rb +410 -0
- data/lib/mxrb/model/project.rb +187 -0
- data/lib/mxrb/model/unit.rb +48 -0
- data/lib/mxrb/module_initializer.rb +75 -0
- data/lib/mxrb/official_marketplace/content_api.rb +292 -0
- data/lib/mxrb/official_marketplace/dependency_resolver.rb +329 -0
- data/lib/mxrb/official_marketplace/lifecycle.rb +367 -0
- data/lib/mxrb/official_marketplace/module_package_importer.rb +318 -0
- data/lib/mxrb/official_marketplace/widget_package_installer.rb +414 -0
- data/lib/mxrb/official_marketplace.rb +720 -0
- data/lib/mxrb/oql/analyzer.rb +155 -0
- data/lib/mxrb/oql/index_advisor.rb +85 -0
- data/lib/mxrb/oql/plan_analyzer.rb +185 -0
- data/lib/mxrb/oql/server.rb +132 -0
- data/lib/mxrb/oql/sql_server_plan_analyzer.rb +190 -0
- data/lib/mxrb/oql/sql_server_workload_analyzer.rb +80 -0
- data/lib/mxrb/oql/workload_analyzer.rb +175 -0
- data/lib/mxrb/oql/workload_baseline.rb +60 -0
- data/lib/mxrb/oql.rb +424 -0
- data/lib/mxrb/project_lifecycle.rb +76 -0
- data/lib/mxrb/protocols/plan.rb +86 -0
- data/lib/mxrb/protocols.rb +123 -0
- data/lib/mxrb/runtime/database_workspace.rb +677 -0
- data/lib/mxrb/runtime/docker_executor.rb +41 -0
- data/lib/mxrb/runtime/docker_workspace.rb +29 -0
- data/lib/mxrb/runtime/executor.rb +169 -0
- data/lib/mxrb/runtime/java_locator.rb +26 -0
- data/lib/mxrb/runtime/native.rb +474 -0
- data/lib/mxrb/runtime/sql_server_database.rb +146 -0
- data/lib/mxrb/runtime/toolchain.rb +82 -0
- data/lib/mxrb/scaffold/cli.rb +113 -0
- data/lib/mxrb/scaffold/generator.rb +246 -0
- data/lib/mxrb/scaffold/help.rb +80 -0
- data/lib/mxrb/scaffold/page_templates.rb +54 -0
- data/lib/mxrb/scaffold/recipes.rb +198 -0
- data/lib/mxrb/scaffold/registry.rb +82 -0
- data/lib/mxrb/scaffold/templates.rb +723 -0
- data/lib/mxrb/scaffold/transaction.rb +84 -0
- data/lib/mxrb/schema/tables.rb +55 -0
- data/lib/mxrb/semantic/analyzer.rb +473 -0
- data/lib/mxrb/semantic/batch_plan.rb +68 -0
- data/lib/mxrb/semantic/domain_mutator.rb +419 -0
- data/lib/mxrb/semantic/embedder.rb +51 -0
- data/lib/mxrb/semantic/extractor.rb +290 -0
- data/lib/mxrb/semantic/index.rb +623 -0
- data/lib/mxrb/semantic/inliner.rb +216 -0
- data/lib/mxrb/semantic/mover.rb +153 -0
- data/lib/mxrb/semantic/onnx_embedder.rb +34 -0
- data/lib/mxrb/semantic/remover.rb +70 -0
- data/lib/mxrb/semantic/renamer.rb +211 -0
- data/lib/mxrb/semantic/tfidf_embedder.rb +46 -0
- data/lib/mxrb/semantic/vec_store.rb +75 -0
- data/lib/mxrb/team_server.rb +390 -0
- data/lib/mxrb/templates/project/10.24.0.73019.json +32 -0
- data/lib/mxrb/templates/project/11.12.1.json +32 -0
- data/lib/mxrb/templates/project/6.10.8.json +50 -0
- data/lib/mxrb/templates/project/7.17.0.json +50 -0
- data/lib/mxrb/templates/project/7.5.0.json +50 -0
- data/lib/mxrb/templates/project/9.6.1.29396.json +50 -0
- data/lib/mxrb/version.rb +5 -0
- data/lib/mxrb/widget_package.rb +338 -0
- data/lib/mxrb/widget_synchronizer.rb +31 -0
- data/lib/mxrb/writer.rb +3775 -0
- data/lib/mxrb.rb +188 -0
- data/marketplace/catalog.json +10 -0
- data/marketplace/modules/shared-kernel/domain/README.md +4 -0
- data/marketplace/modules/shared-kernel/module.rb +5 -0
- data/marketplace/modules/shared-kernel/mxrb-module.json +9 -0
- metadata +447 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "securerandom"
|
|
4
|
+
require "set"
|
|
5
|
+
|
|
6
|
+
module Mxrb
|
|
7
|
+
module Semantic
|
|
8
|
+
# Plan produced by Extractor#plan. Describes what will be extracted and
|
|
9
|
+
# applies the change atomically when apply! is called.
|
|
10
|
+
class ExtractionPlan
|
|
11
|
+
attr_reader :source, :new_name, :selected_ids
|
|
12
|
+
|
|
13
|
+
def initialize(project:, source:, new_name:, selected_ids:,
|
|
14
|
+
inner_objects:, inner_flows:,
|
|
15
|
+
entry_flow:, exit_flow:,
|
|
16
|
+
source_doc:, source_raw:)
|
|
17
|
+
@project = project
|
|
18
|
+
@source = source
|
|
19
|
+
@new_name = new_name
|
|
20
|
+
@selected_ids = selected_ids
|
|
21
|
+
@inner_objects = inner_objects
|
|
22
|
+
@inner_flows = inner_flows
|
|
23
|
+
@entry_flow = entry_flow
|
|
24
|
+
@exit_flow = exit_flow
|
|
25
|
+
@source_doc = source_doc
|
|
26
|
+
@source_raw = source_raw
|
|
27
|
+
@applied = false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def applied? = @applied
|
|
31
|
+
|
|
32
|
+
def changes
|
|
33
|
+
[
|
|
34
|
+
"extract #{@inner_objects.size} activit#{@inner_objects.size == 1 ? 'y' : 'ies'} " \
|
|
35
|
+
"from #{@source.qualified_name} into #{@new_name}",
|
|
36
|
+
"replace selection in #{@source.qualified_name} with call to #{@new_name}"
|
|
37
|
+
]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def apply!
|
|
41
|
+
raise ArgumentError, "extraction plan was already applied" if applied?
|
|
42
|
+
|
|
43
|
+
module_unit_id = find_module_unit_id
|
|
44
|
+
@project.mpr.transaction do
|
|
45
|
+
insert_extracted_microflow!(module_unit_id)
|
|
46
|
+
patch_source_microflow!
|
|
47
|
+
end
|
|
48
|
+
@project.refresh!
|
|
49
|
+
@applied = true
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def find_module_unit_id
|
|
56
|
+
mod = @project.modules.find { _1.name == @source.module_name }
|
|
57
|
+
raise ArgumentError, "cannot find module #{@source.module_name.inspect}" unless mod
|
|
58
|
+
|
|
59
|
+
mod.id
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def insert_extracted_microflow!(module_unit_id)
|
|
63
|
+
local_name = @new_name.split(".", 2).last
|
|
64
|
+
start_id = SecureRandom.uuid
|
|
65
|
+
end_id = SecureRandom.uuid
|
|
66
|
+
first_id = @entry_flow["DestinationPointer"]
|
|
67
|
+
last_id = @exit_flow["OriginPointer"]
|
|
68
|
+
|
|
69
|
+
objects = [
|
|
70
|
+
event_doc(start_id, "Microflows$StartEvent"),
|
|
71
|
+
*@inner_objects,
|
|
72
|
+
event_doc(end_id, "Microflows$EndEvent")
|
|
73
|
+
]
|
|
74
|
+
flows = [
|
|
75
|
+
simple_flow_doc(start_id, first_id),
|
|
76
|
+
*@inner_flows,
|
|
77
|
+
simple_flow_doc(last_id, end_id)
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
doc = {
|
|
81
|
+
"$ID" => SecureRandom.uuid,
|
|
82
|
+
"$Type" => "Microflows$Microflow",
|
|
83
|
+
"Name" => local_name,
|
|
84
|
+
"Documentation" => "",
|
|
85
|
+
"AllowConcurrentExecution" => true,
|
|
86
|
+
"MarkAsUsed" => false,
|
|
87
|
+
"Excluded" => false,
|
|
88
|
+
"MicroflowReturnType" => { "$ID" => SecureRandom.uuid, "$Type" => "DataTypes$VoidType" },
|
|
89
|
+
"AllowedModuleRoles" => IO::BsonCodec.build_array([]),
|
|
90
|
+
"ObjectCollection" => {
|
|
91
|
+
"$ID" => SecureRandom.uuid,
|
|
92
|
+
"$Type" => "Microflows$MicroflowObjectCollection",
|
|
93
|
+
"Objects" => IO::BsonCodec.build_array(objects)
|
|
94
|
+
},
|
|
95
|
+
"Flows" => IO::BsonCodec.build_array(flows)
|
|
96
|
+
}
|
|
97
|
+
@project.mpr.insert_unit(
|
|
98
|
+
container_uuid: module_unit_id,
|
|
99
|
+
containment_name: "Documents",
|
|
100
|
+
contents_doc: doc
|
|
101
|
+
)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def patch_source_microflow!
|
|
105
|
+
call_id = SecureRandom.uuid
|
|
106
|
+
call_activity = call_activity_doc(call_id)
|
|
107
|
+
|
|
108
|
+
removed_ids = @selected_ids
|
|
109
|
+
origin_id = @entry_flow["OriginPointer"]
|
|
110
|
+
dest_id = @exit_flow["DestinationPointer"]
|
|
111
|
+
|
|
112
|
+
# Rebuild objects: keep non-selected, add call activity
|
|
113
|
+
all_objects = normalize_all(parse_array(@source_doc["ObjectCollection"]["Objects"]))
|
|
114
|
+
kept_objects = all_objects.reject { removed_ids.include?(_1["$ID"]) }
|
|
115
|
+
kept_objects << call_activity
|
|
116
|
+
|
|
117
|
+
# Rebuild flows: drop entry/exit flows and inner flows, add two new ones
|
|
118
|
+
inner_flow_ids = @inner_flows.map { _1["$ID"] }.to_set
|
|
119
|
+
removed_flow_ids = inner_flow_ids + [@entry_flow["$ID"], @exit_flow["$ID"]].compact.to_set
|
|
120
|
+
all_flows = normalize_all(parse_array(@source_doc["Flows"]))
|
|
121
|
+
kept_flows = all_flows.reject { removed_flow_ids.include?(_1["$ID"]) }
|
|
122
|
+
kept_flows << simple_flow_doc(origin_id, call_id)
|
|
123
|
+
kept_flows << simple_flow_doc(call_id, dest_id)
|
|
124
|
+
|
|
125
|
+
patched = @source_doc.merge(
|
|
126
|
+
"ObjectCollection" => @source_doc["ObjectCollection"].merge(
|
|
127
|
+
"Objects" => IO::BsonCodec.build_array(kept_objects)
|
|
128
|
+
),
|
|
129
|
+
"Flows" => IO::BsonCodec.build_array(kept_flows)
|
|
130
|
+
)
|
|
131
|
+
@project.mpr.update_unit(@source_raw.fetch("UnitID"), patched)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def event_doc(id, type)
|
|
135
|
+
{ "$ID" => id, "$Type" => type, "RelativeMiddlePoint" => "0;0", "Size" => "20;20" }
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def simple_flow_doc(from_id, to_id)
|
|
139
|
+
{
|
|
140
|
+
"$ID" => SecureRandom.uuid,
|
|
141
|
+
"$Type" => "Microflows$SequenceFlow",
|
|
142
|
+
"OriginPointer" => from_id,
|
|
143
|
+
"DestinationPointer" => to_id,
|
|
144
|
+
"IsErrorHandler" => false,
|
|
145
|
+
"OriginConnectionIndex" => 1,
|
|
146
|
+
"DestinationConnectionIndex" => 3
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def call_activity_doc(id)
|
|
151
|
+
{
|
|
152
|
+
"$ID" => id,
|
|
153
|
+
"$Type" => "Microflows$ActionActivity",
|
|
154
|
+
"RelativeMiddlePoint" => "0;0",
|
|
155
|
+
"Size" => "120;60",
|
|
156
|
+
"Action" => {
|
|
157
|
+
"$ID" => SecureRandom.uuid,
|
|
158
|
+
"$Type" => "Microflows$MicroflowCallAction",
|
|
159
|
+
"ErrorHandlingType" => "Rollback",
|
|
160
|
+
"UseReturnVariable" => false,
|
|
161
|
+
"ResultVariableName" => "ReturnValue",
|
|
162
|
+
"MicroflowCall" => {
|
|
163
|
+
"$ID" => SecureRandom.uuid,
|
|
164
|
+
"$Type" => "Microflows$MicroflowCall",
|
|
165
|
+
"Microflow" => @new_name,
|
|
166
|
+
"ParameterMappings" => IO::BsonCodec.build_array([])
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def parse_array(value)
|
|
173
|
+
IO::BsonCodec.parse_array(value)[:items]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
POINTER_KEYS_EP = %w[$ID OriginPointer DestinationPointer].freeze
|
|
177
|
+
|
|
178
|
+
def normalize_ids(hash)
|
|
179
|
+
hash.each_with_object({}) do |(k, v), out|
|
|
180
|
+
out[k] = POINTER_KEYS_EP.include?(k) ? (IO::BsonCodec.extract_id(v) || v) : v
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def normalize_all(arr)
|
|
185
|
+
arr.map { normalize_ids(_1) }
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# Extracts a contiguous subgraph of a microflow's activities into a new
|
|
190
|
+
# microflow and replaces the selection with a call to it.
|
|
191
|
+
class Extractor
|
|
192
|
+
FLOW_KINDS = %i[microflow nanoflow].freeze
|
|
193
|
+
|
|
194
|
+
def initialize(project)
|
|
195
|
+
@project = project
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Plan an extraction.
|
|
199
|
+
#
|
|
200
|
+
# @param source_name [String] qualified name of the source microflow
|
|
201
|
+
# @param as [String] qualified name for the new extracted microflow
|
|
202
|
+
# @param object_ids [Array] $ID values of the objects to extract
|
|
203
|
+
def plan(source_name, as:, object_ids:)
|
|
204
|
+
source = resolve(source_name)
|
|
205
|
+
raise ArgumentError, "#{source.qualified_name} is not a microflow or nanoflow" \
|
|
206
|
+
unless FLOW_KINDS.include?(source.kind)
|
|
207
|
+
|
|
208
|
+
source_module = source.qualified_name.split(".").first
|
|
209
|
+
new_module = as.split(".").first
|
|
210
|
+
raise ArgumentError, "extracted microflow must be in the same module (#{source_module})" \
|
|
211
|
+
unless new_module == source_module
|
|
212
|
+
|
|
213
|
+
raise ArgumentError, "#{as.inspect} already exists" if @project.find_artifact(as)
|
|
214
|
+
raise ArgumentError, "object_ids cannot be empty" if object_ids.empty?
|
|
215
|
+
|
|
216
|
+
raw = @project.raw_unit(source.unit_id)
|
|
217
|
+
doc = @project.parse_bson(raw)
|
|
218
|
+
|
|
219
|
+
all_objects = parse_array(doc["ObjectCollection"]["Objects"]).map { normalize_ids(_1) }
|
|
220
|
+
all_flows = parse_array(doc["Flows"]).map { normalize_ids(_1) }
|
|
221
|
+
by_id = all_objects.to_h { [_1["$ID"], _1] }
|
|
222
|
+
|
|
223
|
+
selected = Set.new(object_ids.map { IO::BsonCodec.extract_id(_1)&.to_s || _1.to_s })
|
|
224
|
+
missing = selected - by_id.keys.to_set
|
|
225
|
+
raise ArgumentError, "unknown object IDs: #{missing.to_a.join(', ')}" unless missing.empty?
|
|
226
|
+
|
|
227
|
+
# Reject selection of start/end events — those belong to the frame
|
|
228
|
+
all_objects.each do |obj|
|
|
229
|
+
if selected.include?(obj["$ID"]) && %w[
|
|
230
|
+
Microflows$StartEvent Microflows$EndEvent
|
|
231
|
+
].include?(obj["$Type"])
|
|
232
|
+
raise ArgumentError, "cannot include start/end event in extraction selection"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
inner_flows = all_flows.select do
|
|
237
|
+
selected.include?(_1["OriginPointer"]) && selected.include?(_1["DestinationPointer"])
|
|
238
|
+
end
|
|
239
|
+
entry_flows = all_flows.select do
|
|
240
|
+
!selected.include?(_1["OriginPointer"]) && selected.include?(_1["DestinationPointer"])
|
|
241
|
+
end
|
|
242
|
+
exit_flows = all_flows.select do
|
|
243
|
+
selected.include?(_1["OriginPointer"]) && !selected.include?(_1["DestinationPointer"])
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
if entry_flows.size != 1 || exit_flows.size != 1
|
|
247
|
+
raise ArgumentError,
|
|
248
|
+
"selection must have exactly one entry point (found #{entry_flows.size}) " \
|
|
249
|
+
"and one exit point (found #{exit_flows.size})"
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
inner_objects = all_objects.select { selected.include?(_1["$ID"]) }
|
|
253
|
+
|
|
254
|
+
ExtractionPlan.new(
|
|
255
|
+
project: @project,
|
|
256
|
+
source: source,
|
|
257
|
+
new_name: as,
|
|
258
|
+
selected_ids: selected,
|
|
259
|
+
inner_objects: inner_objects,
|
|
260
|
+
inner_flows: inner_flows,
|
|
261
|
+
entry_flow: entry_flows.first,
|
|
262
|
+
exit_flow: exit_flows.first,
|
|
263
|
+
source_doc: doc,
|
|
264
|
+
source_raw: raw
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
private
|
|
269
|
+
|
|
270
|
+
def resolve(name)
|
|
271
|
+
artifact = @project.find_artifact(name)
|
|
272
|
+
return artifact if artifact
|
|
273
|
+
|
|
274
|
+
raise KeyError, "unknown Mendix artifact #{name.inspect}"
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def parse_array(value)
|
|
278
|
+
IO::BsonCodec.parse_array(value)[:items]
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
POINTER_KEYS = %w[$ID OriginPointer DestinationPointer].freeze
|
|
282
|
+
|
|
283
|
+
def normalize_ids(hash)
|
|
284
|
+
hash.each_with_object({}) do |(k, v), out|
|
|
285
|
+
out[k] = POINTER_KEYS.include?(k) ? (IO::BsonCodec.extract_id(v) || v) : v
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|