use super::db::{CONTAINS, Element, Requirement, RequirementDb};
#[derive(Clone, Debug)]
pub(crate) struct GraphNode<'a> {
pub(crate) id: &'a str,
pub(crate) requirement: Option<&'a Requirement>,
pub(crate) element: Option<&'a Element>,
pub(crate) css_styles: &'a [String],
pub(crate) css_classes: String,
}
#[derive(Clone, Debug)]
pub(crate) struct GraphEdge<'a> {
pub(crate) id: String,
pub(crate) start: Option<&'a str>,
pub(crate) end: Option<&'a str>,
pub(crate) kind: &'a str,
pub(crate) contains: bool,
}
#[derive(Clone, Debug)]
pub(crate) struct RequirementGraph<'a> {
pub(crate) nodes: Vec<GraphNode<'a>>,
pub(crate) edges: Vec<GraphEdge<'a>>,
pub(crate) direction: &'a str,
}
pub(crate) fn build_requirement_graph(db: &RequirementDb) -> RequirementGraph<'_> {
let mut nodes = Vec::new();
for r in db.requirements.values() {
nodes.push(GraphNode {
id: &r.name,
requirement: Some(r),
element: None,
css_styles: &r.css_styles,
css_classes: r.classes.join(" "),
});
}
for e in db.elements.values() {
nodes.push(GraphNode {
id: &e.name,
requirement: None,
element: Some(e),
css_styles: &e.css_styles,
css_classes: e.classes.join(" "),
});
}
let has = |id: &str| db.requirements.contains(id) || db.elements.contains(id);
let edges = db
.relations
.iter()
.enumerate()
.map(|(index, r)| GraphEdge {
id: format!("{}-{}-{index}", r.src, r.dst),
start: has(&r.src).then_some(r.src.as_str()),
end: has(&r.dst).then_some(r.dst.as_str()),
kind: &r.kind,
contains: r.kind == CONTAINS,
})
.collect();
RequirementGraph {
nodes,
edges,
direction: &db.direction,
}
}