use crate::args::validate::{
validate_string_not_blank, ObjectValidationError, StringValidationError,
};
use crate::define_object;
use crate::objects::blueprint_folder::BlueprintFolder;
use crate::objects::id::TypedId;
use crate::objects::object::*;
use crate::objects::{ExpiredConnectionError, FromObjectScopeError};
use crate::persistence::project::ProjectError;
use crate::types::location::FolderPosition;
use sqrite::connection::{Connection, DbError, RcRefCellExtension};
use std::fmt::Debug;
use std::rc::Rc;
use tracing::*;
#[derive(thiserror::Error, Debug)]
pub enum BlueprintError {
#[error("error interfacing with project: {0}")]
ProjectError(#[from] ProjectError),
#[error("connection has expired")]
ExpiredConnection(#[from] ExpiredConnectionError),
#[error("error interfacing with database: {0}")]
DbError(#[from] DbError),
#[error("unable to validate object: {0}")]
ObjectValidationError(#[from] ObjectValidationError),
#[error("unable to validate string argument: {0}")]
StringValidationError(#[from] StringValidationError),
#[error("unable to interface with blueprint as object: {0}")]
ObjectError(#[from] ObjectHelperError),
#[error("invalid scope: {0}")]
InvalidScope(#[from] FromObjectScopeError),
}
pub struct BlueprintScope;
impl BlueprintScope {
pub fn from_object_scope(scope: ObjectScope) -> Result<BlueprintScope, FromObjectScopeError> {
match scope {
ObjectScope::Blueprints => Ok(BlueprintScope),
v => Err(FromObjectScopeError::InvalidScope("blueprint", v)),
}
}
pub fn to_object_scope(&self) -> ObjectScope {
ObjectScope::Blueprints
}
}
define_object!(Blueprint, BlueprintFolder, BlueprintScope, BlueprintError);
impl Blueprint {
#[instrument(level = Level::INFO, skip(conn, name, information), fields(name = name.as_ref()))]
pub fn new(
conn: Rc<Connection>,
parent_folder: Option<&BlueprintFolder>,
position: FolderPosition,
name: impl AsRef<str>,
information: impl AsRef<str>,
) -> Result<Self, BlueprintError> {
validate_string_not_blank(&name)?;
let blueprint = conn.transaction_rc(|conn| {
let id = object_create(
conn.clone(),
ObjectType::Blueprint,
ObjectScope::Blueprints,
parent_folder.map(|v| v.to_folder()),
position,
name,
information,
)
.map_err(|e| DbError::TransactionError(e.to_string()))?;
conn.execute("INSERT INTO `blueprints`(`id`) VALUES(?)", id)?;
Ok(Blueprint {
conn: Rc::downgrade(&conn),
id,
})
})?;
Ok(blueprint)
}
}