use crate::context::FactoryContext;
use crate::traits::TraitRegistry;
use crate::Result;
pub struct FactoryBuilder<F, T> {
factory: F,
trait_names: Vec<String>,
overrides: Vec<(String, serde_json::Value)>,
_phantom: std::marker::PhantomData<T>,
}
impl<F, T> FactoryBuilder<F, T>
where
F: BuildableFactory<T>,
{
pub fn new(factory: F) -> Self {
Self {
factory,
trait_names: Vec::new(),
overrides: Vec::new(),
_phantom: std::marker::PhantomData,
}
}
pub fn with_trait(mut self, name: &str) -> Self {
self.trait_names.push(name.to_string());
self
}
pub fn set(mut self, field: &str, value: serde_json::Value) -> Self {
self.overrides.push((field.to_string(), value));
self
}
pub fn build(self, ctx: &mut FactoryContext) -> Result<T> {
for (field, value) in &self.overrides {
ctx.set_override(field, value.clone());
}
let mut entity = self.factory.build_base(ctx);
let registry = self.factory.trait_registry();
for name in &self.trait_names {
registry.apply(name, &mut entity)?;
}
self.factory.apply_overrides(&mut entity, &self.overrides);
ctx.clear_overrides();
Ok(entity)
}
pub async fn create(self, ctx: &mut FactoryContext) -> Result<T> {
for (field, value) in &self.overrides {
ctx.set_override(field, value.clone());
}
let mut entity = self.factory.build_base(ctx);
let registry = self.factory.trait_registry();
for name in &self.trait_names {
registry.apply(name, &mut entity)?;
}
self.factory.apply_overrides(&mut entity, &self.overrides);
let result = self.factory.persist(entity, ctx).await?;
ctx.clear_overrides();
Ok(result)
}
}
pub trait BuildableFactory<T>: Send + Sync {
fn build_base(&self, ctx: &mut FactoryContext) -> T;
fn trait_registry(&self) -> &TraitRegistry<T>;
fn apply_overrides(&self, entity: &mut T, overrides: &[(String, serde_json::Value)]);
fn persist(
&self,
entity: T,
ctx: &mut FactoryContext,
) -> impl std::future::Future<Output = Result<T>> + Send;
}