use std::path::PathBuf;
use std::sync::Arc;
use eure_env::Target;
use query_flow::{Db, QueryError, query};
use thisisplural::Plural;
use crate::report::ErrorReports;
use super::assets::{Glob, TextFile};
use super::schema::{ValidateAgainstExplicitSchema, ValidateAgainstSchema};
#[query]
pub fn validate_document(
db: &impl Db,
doc_file: TextFile,
schema_file: Option<TextFile>,
) -> Result<ErrorReports, QueryError> {
if let Some(sf) = schema_file {
match db.query(ValidateAgainstExplicitSchema::new(doc_file, sf)) {
Ok(reports) => Ok(reports.as_ref().clone()),
Err(QueryError::UserError(e)) => {
if let Some(reports) = e.downcast_ref::<ErrorReports>() {
Ok(reports.clone())
} else {
Err(QueryError::UserError(e))
}
}
Err(other) => Err(other),
}
} else {
match db.query(ValidateAgainstSchema::new(doc_file.clone())) {
Ok(reports) => Ok(reports.as_ref().clone()),
Err(QueryError::UserError(e)) => {
if let Some(reports) = e.downcast_ref::<ErrorReports>() {
Ok(reports.clone())
} else {
Err(QueryError::UserError(e))
}
}
Err(other) => Err(other),
}
}
}
#[derive(Clone, PartialEq, Debug, Default)]
pub struct TargetValidationResult {
pub files_checked: usize,
pub file_errors: Vec<(TextFile, ErrorReports)>,
}
impl TargetValidationResult {
pub fn is_ok(&self) -> bool {
self.file_errors.is_empty()
}
pub fn error_count(&self) -> usize {
self.file_errors.len()
}
}
#[derive(Clone, PartialEq, Debug, Default, Plural)]
pub struct ValidateTargetResult(Vec<(TextFile, ErrorReports)>);
#[query]
pub fn validate_target(
db: &impl Db,
target: Target,
config_dir: PathBuf,
) -> Result<ValidateTargetResult, QueryError> {
let schema_file = target
.schema
.as_ref()
.map(|schema_path| TextFile::resolve(schema_path, &config_dir))
.transpose()?;
let files: Vec<TextFile> = target
.globs
.iter()
.map(|glob_pattern| {
let glob_key = Glob::new(config_dir.clone(), glob_pattern.clone());
db.asset(glob_key)
})
.collect::<Vec<_>>()
.into_iter()
.collect::<Result<Vec<_>, QueryError>>()?
.into_iter()
.flat_map(|result| result.0.clone())
.collect();
files
.into_iter()
.map(|file| {
db.query(ValidateDocument::new(file.clone(), schema_file.clone()))
.map(|reports| (file, reports.as_ref().clone()))
})
.collect()
}
#[derive(Clone, PartialEq, Debug, Default)]
pub struct TargetsValidationResult {
pub target_results: Vec<(String, TargetValidationResult)>,
}
impl TargetsValidationResult {
pub fn is_ok(&self) -> bool {
self.target_results.iter().all(|(_, r)| r.is_ok())
}
pub fn total_files_checked(&self) -> usize {
self.target_results
.iter()
.map(|(_, r)| r.files_checked)
.sum()
}
pub fn total_error_count(&self) -> usize {
self.target_results
.iter()
.map(|(_, r)| r.error_count())
.sum()
}
}
#[derive(Clone, PartialEq, Debug, Default, Plural)]
pub struct ValidateTargetsResult(Vec<(String, ValidateTargetResult)>);
#[query]
pub fn validate_targets(
db: &impl Db,
targets: Arc<Vec<(String, Target)>>,
config_dir: PathBuf,
) -> Result<ValidateTargetsResult, QueryError> {
targets
.iter()
.map(|(name, target)| {
db.query(ValidateTarget::new(target.clone(), config_dir.clone()))
.map(|result| (name.clone(), result.as_ref().clone()))
})
.collect()
}