mod error;
use std::sync::Arc;
use log::{error, warn};
pub use crate::validator::error::Error;
use crate::{
data::interface::Provider,
mapper::{variant::Config, variant::Mapper},
parser::HgvsVariant,
};
pub trait Validateable {
fn validate(&self) -> Result<(), Error>;
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ValidationLevel {
Null,
Intrinsic,
Full,
}
impl ValidationLevel {
pub fn validator(
&self,
strict: bool,
provider: Arc<dyn Provider + Send + Sync>,
) -> Arc<dyn Validator + Send + Sync> {
match self {
ValidationLevel::Null => Arc::new(NullValidator::new()),
ValidationLevel::Intrinsic => Arc::new(IntrinsicValidator::new(strict)),
ValidationLevel::Full => Arc::new(FullValidator::new(strict, provider)),
}
}
}
pub trait Validator {
fn is_strict(&self) -> bool;
fn validate(&self, var: &HgvsVariant) -> Result<(), Error>;
}
pub struct NullValidator {}
impl NullValidator {
pub fn new() -> Self {
Self {}
}
}
impl Default for NullValidator {
fn default() -> Self {
Self::new()
}
}
impl Validator for NullValidator {
fn is_strict(&self) -> bool {
false
}
fn validate(&self, _var: &HgvsVariant) -> Result<(), Error> {
Ok(())
}
}
pub struct IntrinsicValidator {
strict: bool,
}
impl IntrinsicValidator {
pub fn new(strict: bool) -> Self {
Self { strict }
}
}
impl Validator for IntrinsicValidator {
fn is_strict(&self) -> bool {
self.strict
}
fn validate(&self, var: &HgvsVariant) -> Result<(), Error> {
let res = var.validate();
match (&res, self.is_strict()) {
(Ok(_), _) => Ok(()),
(Err(_), false) => {
warn!("Validation of {} failed: {:?}", var, res);
Ok(())
}
(Err(_), true) => {
error!("Validation of {} failed: {:?}", var, res);
res
}
}
}
}
pub struct ExtrinsicValidator {
strict: bool,
#[allow(dead_code)]
mapper: Mapper,
}
impl ExtrinsicValidator {
pub fn new(strict: bool, provider: Arc<dyn Provider + Send + Sync>) -> Self {
let config = Config {
replace_reference: false,
strict_validation: false,
prevalidation_level: ValidationLevel::Null,
add_gene_symbol: false,
strict_bounds: true,
renormalize_g: false,
genome_seq_available: true,
shuffle_direction: Default::default(),
window_size: 20,
};
Self {
strict,
mapper: Mapper::new(&config, provider),
}
}
}
impl Validator for ExtrinsicValidator {
fn is_strict(&self) -> bool {
self.strict
}
fn validate(&self, var: &HgvsVariant) -> Result<(), Error> {
match var {
HgvsVariant::CdsVariant { .. } | HgvsVariant::TxVariant { .. } => {
let res = self.check_tx_bound(var);
if res.is_err() {
if self.is_strict() {
error!("Validation of {} failed: {:?}", var, res);
return res;
} else {
warn!("Validation of {} failed: {:?}", var, res);
}
}
}
_ => {}
}
{
let res = self.check_cds_bound(var);
if res.is_err() {
if self.is_strict() {
error!("Validation of {} failed: {:?}", var, res);
return res;
} else {
warn!("Validation of {} failed: {:?}", var, res);
}
}
}
{
let res = self.check_ref(var);
if res.is_err() {
if self.is_strict() {
error!("Validation of {} failed: {:?}", var, res);
return res;
} else {
warn!("Validation of {} failed: {:?}", var, res);
}
}
}
Ok(())
}
}
impl ExtrinsicValidator {
fn check_tx_bound(&self, _var: &HgvsVariant) -> Result<(), Error> {
Ok(()) }
fn check_cds_bound(&self, _var: &HgvsVariant) -> Result<(), Error> {
Ok(()) }
fn check_ref(&self, _var: &HgvsVariant) -> Result<(), Error> {
Ok(()) }
}
pub struct FullValidator {
intrinsic: IntrinsicValidator,
extrinsic: ExtrinsicValidator,
}
impl FullValidator {
pub fn new(strict: bool, provider: Arc<dyn Provider + Send + Sync>) -> Self {
Self {
intrinsic: IntrinsicValidator::new(strict),
extrinsic: ExtrinsicValidator::new(strict, provider),
}
}
}
impl Validator for FullValidator {
fn is_strict(&self) -> bool {
self.intrinsic.is_strict()
}
fn validate(&self, var: &HgvsVariant) -> Result<(), Error> {
self.intrinsic.validate(var)?;
self.extrinsic.validate(var)
}
}