use crate::description::DescriptionOwner;
use crate::legend::Legend;
use crate::model::{Edge, EdgeId, Element};
use crate::path::ElementPath;
use crate::validate::{ModelAdmission, UncheckedModel};
#[derive(Debug, Default)]
pub struct ModelBuilder {
unchecked: UncheckedModel,
}
impl ModelBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
let title = title.into();
self.unchecked.model.title = Some(title);
self
}
pub fn with_subtitle(mut self, subtitle: impl Into<String>) -> Self {
let subtitle = subtitle.into();
self.unchecked.model.subtitle = Some(subtitle);
self
}
pub fn with_description(mut self, description: impl Into<String>) -> Self {
let description = description.into();
self.unchecked.model.description = Some(description);
self
}
pub fn with_legend(mut self, legend: Legend) -> Self {
self.unchecked.model.legend = Some(legend);
self
}
pub fn add_top_level(&mut self, id: &str, element: Element) -> ElementRef {
let path = ElementPath::root();
let root = ElementRef { path };
self.add_child(&root, id, element)
}
pub fn add_child(&mut self, parent: &ElementRef, id: &str, element: Element) -> ElementRef {
let path = parent.path.child(id);
let elements = &mut self.unchecked.model.elements;
let is_duplicate = elements.contains_key(&path);
if is_duplicate {
let duplicate_path = path.clone();
let duplicate_declaration = (duplicate_path, element);
self.unchecked
.duplicate_declarations
.push(duplicate_declaration);
return ElementRef { path };
}
let inserted_path = path.clone();
elements.insert(inserted_path, element);
ElementRef { path }
}
pub fn add_edge(&mut self, from: &ElementRef, to: &ElementRef, edge: Edge) -> EdgeId {
let from_path = from.path.clone();
let to_path = to.path.clone();
self.unchecked
.model
.insert_edge_with_next_free_ordinal(from_path, to_path, edge)
}
pub fn describe(&mut self, owner: &DescriptionOwner, description: impl Into<String>) {
let description = description.into();
let model = &mut self.unchecked.model;
match owner {
DescriptionOwner::Diagram => model.description = Some(description),
DescriptionOwner::Element(path) => {
if let Some(element) = model.elements.get_mut(path) {
element.description = Some(description);
}
}
DescriptionOwner::Edge(id) => {
if let Some(edge) = model.edges.get_mut(id) {
edge.description = Some(description);
}
}
}
}
pub fn build(self) -> ModelAdmission {
self.unchecked.admit()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ElementRef {
path: ElementPath,
}
impl ElementRef {
pub fn path(&self) -> &ElementPath {
&self.path
}
}