Skip to content

Commit 84bfbaf

Browse files
committed
component sequence validator
1 parent bea8dd1 commit 84bfbaf

18 files changed

Lines changed: 634 additions & 91 deletions

File tree

bazel/rules/rules_score/examples/seooc/design/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ load(
1717

1818
architectural_design(
1919
name = "sample_seooc_design",
20+
dynamic = [
21+
"dynamic_design.puml",
22+
],
2023
public_api = [
2124
"public_api.puml",
2225
],
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
' *******************************************************************************
2+
' Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
'
4+
' See the NOTICE file(s) distributed with this work for additional
5+
' information regarding copyright ownership.
6+
'
7+
' This program and the accompanying materials are made available under the
8+
' terms of the Apache License Version 2.0 which is available at
9+
' https://www.apache.org/licenses/LICENSE-2.0
10+
'
11+
' SPDX-License-Identifier: Apache-2.0
12+
' *******************************************************************************
13+
14+
@startuml
15+
16+
participant "Unit 1" as unit_1 <<unit>>
17+
participant "Unit 2" as unit_2 <<unit>>
18+
19+
unit_1 -> unit_2 : callMethod1()
20+
unit_2 -> unit_1 : callMethod2()
21+
22+
@enduml

bazel/rules/rules_score/private/dependable_element.bzl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -629,13 +629,14 @@ def _collect_architecture_components(ctx):
629629

630630
return all_components
631631

632-
def _run_validation(ctx, arch_json, static_fbs_files, unit_static_fbs_files):
632+
def _run_validation(ctx, arch_json, static_fbs_files, dynamic_fbs_files, unit_static_fbs_files):
633633
"""Run the architecture verifier tool against a pre-built JSON file.
634634
635635
Args:
636636
ctx: Rule context
637637
arch_json: The architecture JSON File object (already declared and written)
638638
static_fbs_files: List of static component-diagram FlatBuffer files
639+
dynamic_fbs_files: List of dynamic component-diagram FlatBuffer files
639640
unit_static_fbs_files: List of static class-diagram FlatBuffer files
640641
641642
Returns:
@@ -646,16 +647,20 @@ def _run_validation(ctx, arch_json, static_fbs_files, unit_static_fbs_files):
646647

647648
validation_args = ctx.actions.args()
648649
validation_args.add("--architecture-json", arch_json)
649-
validation_args.add_all("--component-fbs", static_fbs_files)
650-
validation_args.add_all("--class-fbs", unit_static_fbs_files)
650+
if static_fbs_files:
651+
validation_args.add_all("--component-fbs", static_fbs_files)
652+
if dynamic_fbs_files:
653+
validation_args.add_all("--sequence-fbs", dynamic_fbs_files)
654+
if unit_static_fbs_files:
655+
validation_args.add_all("--class-fbs", unit_static_fbs_files)
651656
validation_args.add("--output", validation_log)
652657
validation_args.add("--log-level", get_log_level(ctx))
653658
if ctx.attr.maturity == "development":
654659
validation_args.add("--warn-on-errors")
655660

656661
# ctx.actions.run will fail the build if validation_cli returns non-zero exit code
657662
ctx.actions.run(
658-
inputs = [arch_json] + static_fbs_files + unit_static_fbs_files,
663+
inputs = [arch_json] + static_fbs_files + dynamic_fbs_files + unit_static_fbs_files,
659664
outputs = [validation_log],
660665
executable = ctx.executable._validation_cli,
661666
arguments = [validation_args],
@@ -817,9 +822,11 @@ def _dependable_element_index_impl(ctx):
817822
# Collect static FlatBuffers from architectural_design targets (the expected
818823
# static architecture) and verify them against the current architecture.
819824
static_fbs_files = []
825+
dynamic_fbs_files = []
820826
for ad in ctx.attr.architectural_design:
821827
if ArchitecturalDesignInfo in ad:
822828
static_fbs_files.extend(ad[ArchitecturalDesignInfo].static.to_list())
829+
dynamic_fbs_files.extend(ad[ArchitecturalDesignInfo].dynamic.to_list())
823830

824831
# Collect class-diagram FBS files produced by unit_design targets.
825832
unit_static_fbs_files = []
@@ -828,7 +835,7 @@ def _dependable_element_index_impl(ctx):
828835
unit_static_fbs_files.extend(unit_info.unit_design_static_fbs.to_list())
829836

830837
# Run validation; build fails automatically on non-zero exit
831-
validation_log = _run_validation(ctx, arch_json, static_fbs_files, unit_static_fbs_files)
838+
validation_log = _run_validation(ctx, arch_json, static_fbs_files, dynamic_fbs_files, unit_static_fbs_files)
832839

833840
# Both outputs are included so validation always runs in a default build.
834841
# validation_log is also exposed in the debug output group for explicit access.

plantuml/parser/puml_cli/src/main.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use puml_parser::{
2929
use puml_resolver::{
3030
ClassResolver, DiagramResolver, ElementResolver, LogicElement, SequenceResolver, SequenceTree,
3131
};
32-
use puml_serializer::{ClassSerializer, ComponentSerializer};
32+
use puml_serializer::{ClassSerializer, ComponentSerializer, SequenceSerializer};
3333
use puml_utils::{write_fbs_to_file, write_json_to_file, LogLevel};
3434

3535
/// CLI wrapper for LogLevel that implements ValueEnum
@@ -214,13 +214,8 @@ fn serialize_resolved_diagram(resolved_content: &ResolvedDiagram, source_file: &
214214
ResolvedDiagram::Class(resolved_content) => {
215215
ClassSerializer::serialize(resolved_content, source_file)
216216
}
217-
ResolvedDiagram::Sequence(_) => {
218-
log::warn!(
219-
"Sequence diagram serialization is not yet implemented; \
220-
no output will be written for '{}'",
221-
source_file
222-
);
223-
vec![]
217+
ResolvedDiagram::Sequence(resolved_content) => {
218+
SequenceSerializer::serialize(resolved_content, source_file)
224219
}
225220
}
226221
}

plantuml/parser/puml_serializer/src/fbs/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ rust_library(
108108
],
109109
visibility = [
110110
"//plantuml/parser:__subpackages__",
111+
"//validation/core:__subpackages__",
111112
],
112113
deps = [
113114
"@crates//:flatbuffers",

plantuml/parser/puml_serializer/src/serialize/sequence_serializer.rs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,42 +13,33 @@
1313

1414
use flatbuffers::FlatBufferBuilder;
1515
use sequence_fbs::sequence_metamodel as fb;
16-
use sequence_logic::{ConditionType, Event, SequenceNode};
16+
use sequence_logic::{ConditionType, Event, SequenceNode, SequenceTree};
1717

1818
pub struct SequenceSerializer;
1919

2020
impl SequenceSerializer {
21-
pub fn serialize(
22-
nodes: &[SequenceNode],
23-
name: Option<&str>,
24-
source_files: &[String],
25-
version: Option<&str>,
26-
) -> Vec<u8> {
21+
pub fn serialize(diagram: &SequenceTree, source_file: &str) -> Vec<u8> {
2722
let mut builder = FlatBufferBuilder::new();
2823

29-
let name_offset = name.map(|n| builder.create_string(n));
24+
let name_offset = diagram.name.as_deref().map(|n| builder.create_string(n));
3025

31-
let node_offsets: Vec<_> = nodes
26+
let node_offsets: Vec<_> = diagram
27+
.root_interactions
3228
.iter()
3329
.map(|node| Self::serialize_node(&mut builder, node))
3430
.collect();
3531
let nodes_offset = builder.create_vector(&node_offsets);
3632

37-
let source_offsets: Vec<_> = source_files
38-
.iter()
39-
.map(|s| builder.create_string(s))
40-
.collect();
33+
let source_offsets = [builder.create_string(source_file)];
4134
let source_files_offset = builder.create_vector(&source_offsets);
4235

43-
let version_offset = version.map(|v| builder.create_string(v));
44-
4536
let root = fb::SequenceDiagram::create(
4637
&mut builder,
4738
&fb::SequenceDiagramArgs {
4839
name: name_offset,
4940
root_interactions: Some(nodes_offset),
5041
source_files: Some(source_files_offset),
51-
version: version_offset,
42+
version: None,
5243
},
5344
);
5445

validation/core/BUILD

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ rust_library(
2121
"src/models/component_diagram_models.rs",
2222
"src/models/error_models.rs",
2323
"src/models/mod.rs",
24+
"src/models/sequence_diagram_models.rs",
2425
"src/models/shared.rs",
2526
"src/readers/bazel_reader.rs",
2627
"src/readers/class_diagram_reader.rs",
2728
"src/readers/component_diagram_reader.rs",
2829
"src/readers/mod.rs",
30+
"src/readers/sequence_diagram_reader.rs",
2931
"src/validators/bazel_component_validator.rs",
3032
"src/validators/component_class_validator.rs",
3133
"src/validators/component_sequence_validator.rs",
@@ -36,7 +38,9 @@ rust_library(
3638
deps = [
3739
"//plantuml/parser/puml_serializer/src/fbs:class_fbs",
3840
"//plantuml/parser/puml_serializer/src/fbs:component_fbs",
41+
"//plantuml/parser/puml_serializer/src/fbs:sequence_fbs",
3942
"//tools/metamodel:class_diagram",
43+
"//tools/metamodel:sequence_diagram",
4044
"@crates//:flatbuffers",
4145
"@crates//:serde",
4246
"@crates//:serde_json",

validation/core/README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ The package contains two public targets:
2525

2626
## What It Validates
2727

28-
The current implementation supports two validation flows:
28+
The current implementation supports three validation flows:
2929

3030
1. `BazelComponent`: compares the indexed Bazel build graph with the indexed
3131
PlantUML component-diagram structure.
3232
2. `ComponentClass`: compares component-diagram unit aliases with enclosing
3333
namespace IDs observed in class diagrams.
34+
3. `ComponentSequence`: compares component-diagram unit aliases with
35+
caller/callee participants observed in sequence diagrams (exact match).
3436

3537
The CLI builds a `ValidationContext` from the provided inputs, infers which of
3638
these flows are executable, and runs all compatible validators in one pass.
@@ -59,15 +61,18 @@ The CLI accepts the following input families:
5961
- `--architecture-json`: Bazel architecture export consumed by `BazelReader`
6062
- `--component-fbs`: one or more component-diagram FlatBuffers files consumed by
6163
`ComponentDiagramReader`
64+
- `--sequence-fbs`: one or more sequence-diagram FlatBuffers files consumed by
65+
`SequenceDiagramReader`
6266
- `--class-fbs`: one or more class-diagram FlatBuffers files consumed by
6367
`ClassDiagramReader`
6468

6569
The current inference rules are:
6670

6771
- `--architecture-json` + `--component-fbs` enables `BazelComponent`
6872
- `--component-fbs` + `--class-fbs` enables `ComponentClass`
73+
- `--component-fbs` + `--sequence-fbs` enables `ComponentSequence`
6974

70-
If both combinations are present, both validators are executed.
75+
If multiple combinations are present, all compatible validators are executed.
7176

7277
## Run
7378

@@ -83,6 +88,7 @@ Run it directly:
8388
bazel run //validation/core:validation_cli -- \
8489
--architecture-json path/to/architecture.json \
8590
--component-fbs path/to/component.fbs.bin \
91+
--sequence-fbs path/to/sequence.fbs.bin \
8692
--class-fbs path/to/class.fbs.bin \
8793
--output path/to/validation.log
8894
```

validation/core/docs/assets/validation_core_flow.puml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ title Validation Core Runtime Flow
1717
participant "CLI" as cli
1818
participant "BazelReader" as bazel_reader
1919
participant "ComponentDiagramReader" as component_reader
20+
participant "SequenceDiagramReader" as sequence_reader
2021
participant "ClassDiagramReader" as class_reader
2122
participant "ValidationContext" as context
2223
participant "validate_bazel_component()" as bazel_validator
24+
participant "validate_component_sequence()" as sequence_validator
2325
participant "validate_component_class()" as class_validator
2426
participant "Errors" as errors
2527

@@ -38,6 +40,12 @@ opt component fbs provided
3840
cli -> cli: to_diagram_architecture(&mut base_errors)
3941
end
4042

43+
opt sequence fbs provided
44+
cli -> sequence_reader: read(paths)
45+
sequence_reader --> cli: SequenceDiagramInputs
46+
cli -> cli: to_sequence_diagram_index(&mut base_errors)
47+
end
48+
4149
opt class fbs provided
4250
cli -> class_reader: read(paths)
4351
class_reader --> cli: ClassDiagramInputs
@@ -53,6 +61,12 @@ opt bazel + component available
5361
cli -> errors: merge_errors(...)
5462
end
5563

64+
opt component + sequence available
65+
cli -> sequence_validator: validate_component_sequence(..., Errors::default())
66+
sequence_validator --> cli: Errors
67+
cli -> errors: merge_errors(...)
68+
end
69+
5670
opt component + class available
5771
cli -> class_validator: validate_component_class(..., Errors::default())
5872
class_validator --> cli: Errors

validation/core/docs/assets/validation_core_overview.puml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ package "validation/core" {
2929
package "readers" {
3030
class "BazelReader"
3131
class "ComponentDiagramReader"
32+
class "SequenceDiagramReader"
3233
class "ClassDiagramReader"
3334
}
3435

3536
package "models" {
3637
class "BazelArchitecture"
3738
class "ComponentDiagramArchitecture"
39+
class "SequenceDiagramInputs"
40+
class "SequenceDiagramIndex"
3841
class "ClassDiagramInputs"
3942
class "ClassDiagramIndex"
4043
class "Errors"
@@ -50,27 +53,33 @@ package "validation/core" {
5053
+base_errors: Errors
5154
+bazel: Option<BazelArchitecture>
5255
+component: Option<ComponentDiagramArchitecture>
56+
+sequence: Option<SequenceDiagramIndex>
5357
+class: Option<ClassDiagramIndex>
5458
}
5559
}
5660

5761
cli --> BazelReader : reads architecture json
5862
cli --> ComponentDiagramReader : reads component fbs
63+
cli --> SequenceDiagramReader : reads sequence fbs
5964
cli --> ClassDiagramReader : reads class fbs
6065

6166
BazelReader --> BazelArchitecture
6267
ComponentDiagramReader --> ComponentDiagramArchitecture
68+
SequenceDiagramReader --> SequenceDiagramInputs
6369
ClassDiagramReader --> ClassDiagramInputs
70+
cli --> SequenceDiagramIndex : to_sequence_diagram_index(...)
6471
cli --> ClassDiagramIndex : to_class_diagram_index(...)
6572

6673
cli --> context : builds
6774
context --> Errors
6875
context --> BazelArchitecture
6976
context --> ComponentDiagramArchitecture
77+
context --> SequenceDiagramIndex
7078
context --> ClassDiagramIndex
7179

7280
cli --> "validate_bazel_component()" : when bazel + component exist
7381
cli --> "validate_component_class()" : when component + class exist
82+
cli --> "validate_component_sequence()" : when component + sequence exist
7483

7584
"validate_bazel_component()" --> BazelArchitecture
7685
"validate_bazel_component()" --> ComponentDiagramArchitecture
@@ -80,6 +89,10 @@ cli --> "validate_component_class()" : when component + class exist
8089
"validate_component_class()" --> ClassDiagramIndex
8190
"validate_component_class()" --> Errors
8291

92+
"validate_component_sequence()" --> ComponentDiagramArchitecture
93+
"validate_component_sequence()" --> SequenceDiagramIndex
94+
"validate_component_sequence()" --> Errors
95+
8396
note bottom of cli
8497
CLI owns orchestration:
8598
- input loading

0 commit comments

Comments
 (0)