// Copyright 2025 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Immutable data model for functional architecture
///|
/// Graph-scoped metadata values aligned with the reference's current config data shape.
pub(all) enum GraphDataValue {
Text(String)
StringArray(Array[String])
} derive(Eq, Debug)
///|
/// Immutable legend configuration
pub struct LegendModel {
title : String?
position : LegendPosition
entries : Array[LegendEntryInput]
fill : String?
stroke : String?
padding : Double
entry_gap : Double
icon_size : Double
} derive(Debug)
///|
pub fn LegendModel::new() -> LegendModel {
{
title: None,
position: BottomRight,
entries: [],
fill: Some("#ffffff"),
stroke: Some("#cccccc"),
padding: 12.0,
entry_gap: 8.0,
icon_size: 20.0,
}
}
///|
#warnings("-struct_never_constructed")
pub struct FragmentOperandModel {
/// Immutable sequence fragment operand
condition : String?
separator_y : Double
} derive(Debug)
///|
/// Immutable sequence fragment
pub struct SequenceFragmentModel {
fragment_type : String
condition : String?
bbox : Box?
start_index : Int
end_index : Int
operands : Array[FragmentOperandModel]
} derive(Debug)
///|
pub fn SequenceFragmentModel::new(
fragment_type : String,
start_index : Int,
end_index : Int,
) -> SequenceFragmentModel {
{
fragment_type,
condition: None,
bbox: None,
start_index,
end_index,
operands: [],
}
}
///|
pub struct ObjectReference {
range : @lexer.Range
key_path_index : Int
in_edge : Bool
scope_abs_id_syntax : String?
source_path : String?
primary : Bool
due_to_glob : Bool
due_to_lazy_glob : Bool
} derive(Eq, Debug)
///|
pub fn ObjectReference::new(
range : @lexer.Range,
key_path_index : Int,
in_edge : Bool,
scope_abs_id_syntax : String?,
source_path : String?,
primary : Bool,
due_to_glob : Bool,
due_to_lazy_glob : Bool,
) -> ObjectReference {
{
range,
key_path_index,
in_edge,
scope_abs_id_syntax,
source_path,
primary,
due_to_glob,
due_to_lazy_glob,
}
}
///|
pub struct EdgeReference {
range : @lexer.Range
edge_index : Int
scope_abs_id_syntax : String?
source_path : String?
primary : Bool
due_to_glob : Bool
due_to_lazy_glob : Bool
} derive(Eq, Debug)
///|
pub fn EdgeReference::new(
range : @lexer.Range,
edge_index : Int,
scope_abs_id_syntax : String?,
source_path : String?,
primary : Bool,
due_to_glob : Bool,
due_to_lazy_glob : Bool,
) -> EdgeReference {
{
range,
edge_index,
scope_abs_id_syntax,
source_path,
primary,
due_to_glob,
due_to_lazy_glob,
}
}
///|
/// Immutable style model
pub struct StyleModel {
opacity : StyleValue?
stroke : StyleValue?
fill : StyleValue?
stroke_width : StyleValue?
stroke_dash : StyleValue?
border_radius : StyleValue?
shadow : StyleValue?
three_d : StyleValue?
multiple : StyleValue?
font : StyleValue?
font_size : StyleValue?
font_color : StyleValue?
bold : StyleValue?
italic : StyleValue?
underline : StyleValue?
animated : StyleValue?
filled : StyleValue?
double_border : StyleValue?
text_transform : StyleValue?
font_family : StyleValue?
fill_pattern : StyleValue?
sketch : StyleValue?
curved : StyleValue?
} derive(Eq, Debug)
///|
pub fn StyleModel::new() -> StyleModel {
{
opacity: None,
stroke: None,
fill: None,
stroke_width: None,
stroke_dash: None,
border_radius: None,
shadow: None,
three_d: None,
multiple: None,
font: None,
font_size: None,
font_color: None,
bold: None,
italic: None,
underline: None,
animated: None,
filled: None,
double_border: None,
text_transform: None,
font_family: None,
fill_pattern: None,
sketch: None,
curved: None,
}
}
///|
/// Immutable object model
pub struct ObjectModel {
id : String
id_val : String
id_syntax : String
abs_id_syntax : String
references : Array[ObjectReference]
label : String
shape_type : ShapeType
style : StyleModel
box : Box?
label_box : Box?
children : Array[ObjectModel]
z_index : Int
icon : String?
icon_position : String?
tooltip : String?
tooltip_position : String?
link : String?
label_position : String?
classes : Array[String]
language : String?
sql_constraints : Array[String]
grid_rows : Int?
grid_columns : Int?
grid_gap : Double?
horizontal_gap : Double?
vertical_gap : Double?
grid_column_span : Int?
grid_row_span : Int?
near : String?
top : Int?
left : Int?
direction : String?
} derive(Debug)
///|
pub fn ObjectModel::new(
id : String,
id_val? : String = id,
id_syntax? : String = id,
abs_id_syntax? : String = id,
) -> ObjectModel {
{
id,
id_val,
id_syntax,
abs_id_syntax,
references: [],
label: id_val,
shape_type: Rectangle,
style: StyleModel::new(),
box: None,
label_box: None,
children: [],
z_index: 0,
icon: None,
icon_position: None,
tooltip: None,
tooltip_position: None,
link: None,
label_position: None,
classes: [],
language: None,
sql_constraints: [],
grid_rows: None,
grid_columns: None,
grid_gap: None,
horizontal_gap: None,
vertical_gap: None,
grid_column_span: None,
grid_row_span: None,
near: None,
top: None,
left: None,
direction: None,
}
}
///|
/// Immutable edge model
pub struct EdgeModel {
index : Int
src_id : String
dst_id : String
src_id_syntax : String
dst_id_syntax : String
references : Array[EdgeReference]
classes : Array[String]
src_arrow : Bool
dst_arrow : Bool
src_arrowhead : ArrowheadType
dst_arrowhead : ArrowheadType
src_arrowhead_label : String?
dst_arrowhead_label : String?
src_arrowhead_label_color : String?
dst_arrowhead_label_color : String?
src_anchor : String?
dst_anchor : String?
label : String
icon : String?
icon_position : String?
icon_border_radius : Double?
link : String?
style : StyleModel
route : Array[Point]
bend_points : Array[Point]?
is_curve : Bool
z_index : Int
reference_count : Int
label_box : Box?
src_column_index : Int?
dst_column_index : Int?
} derive(Debug)
///|
pub fn EdgeModel::new(
index : Int,
src_id : String,
dst_id : String,
src_arrow : Bool,
dst_arrow : Bool,
src_id_syntax? : String = src_id,
dst_id_syntax? : String = dst_id,
) -> EdgeModel {
{
index,
src_id,
dst_id,
src_id_syntax,
dst_id_syntax,
references: [],
classes: [],
src_arrow,
dst_arrow,
src_arrowhead: if src_arrow {
Triangle
} else {
None
},
dst_arrowhead: if dst_arrow {
Triangle
} else {
None
},
src_arrowhead_label: None,
dst_arrowhead_label: None,
src_arrowhead_label_color: None,
dst_arrowhead_label_color: None,
src_anchor: None,
dst_anchor: None,
label: "",
icon: None,
icon_position: None,
icon_border_radius: None,
link: None,
style: StyleModel::new(),
route: [],
bend_points: None,
is_curve: false,
z_index: 0,
reference_count: 1,
label_box: None,
src_column_index: None,
dst_column_index: None,
}
}
///|
/// Immutable graph model
pub struct GraphModel {
name : String
root : ObjectModel
objects : Array[ObjectModel]
edges : Array[EdgeModel]
activation_boxes : Array[(String, Box)]
sequence_notes : Array[(String, String, Box)]
sequence_fragments : Array[SequenceFragmentModel]
layers : Array[LayerModel]
scenarios : Array[ScenarioModel]
steps : Array[StepModel]
legend : LegendModel?
is_folder_only : Bool
data : Map[String, GraphDataValue]
} derive(Debug)
///|
#warnings("-struct_never_constructed")
pub struct LayerModel {
/// Immutable layer model
name : String
graph : GraphModel
} derive(Debug)
///|
#warnings("-struct_never_constructed")
pub struct ScenarioModel {
/// Immutable scenario model
name : String
graph : GraphModel
} derive(Debug)
///|
#warnings("-struct_never_constructed")
pub struct StepModel {
/// Immutable step model
name : String
graph : GraphModel
} derive(Debug)
///|
pub fn GraphModel::new(name : String) -> GraphModel {
let root = ObjectModel::new("root")
{
name,
root,
objects: [],
edges: [],
activation_boxes: [],
sequence_notes: [],
sequence_fragments: [],
layers: [],
scenarios: [],
steps: [],
legend: None,
is_folder_only: false,
data: Map([]),
}
}
///|
/// Functional helpers
pub fn ObjectModel::with_label(
self : ObjectModel,
label : String,
) -> ObjectModel {
{ ..self, label, }
}
///|
pub fn ObjectModel::with_box(self : ObjectModel, box : Box?) -> ObjectModel {
{ ..self, box, }
}
///|
pub fn ObjectModel::with_label_box(
self : ObjectModel,
label_box : Box?,
) -> ObjectModel {
{ ..self, label_box, }
}
///|
pub fn ObjectModel::add_child(
self : ObjectModel,
child : ObjectModel,
) -> ObjectModel {
let children = self.children.copy()
children.push(child)
{ ..self, children, }
}
///|
pub fn EdgeModel::with_label(self : EdgeModel, label : String) -> EdgeModel {
{ ..self, label, }
}
///|
pub fn EdgeModel::with_route(
self : EdgeModel,
route : Array[Point],
) -> EdgeModel {
{ ..self, route, }
}
///|
pub fn EdgeModel::with_label_box(
self : EdgeModel,
label_box : Box?,
) -> EdgeModel {
{ ..self, label_box, }
}
///|
pub fn GraphModel::add_object(
self : GraphModel,
obj : ObjectModel,
) -> GraphModel {
let objects = self.objects.copy()
objects.push(obj)
{ ..self, objects, }
}
///|
pub fn GraphModel::add_edge(self : GraphModel, edge : EdgeModel) -> GraphModel {
let edges = self.edges.copy()
edges.push(edge)
{ ..self, edges, }
}
///|
pub fn GraphModel::with_legend(
self : GraphModel,
legend : LegendModel?,
) -> GraphModel {
{ ..self, legend, }
}