use crate::validator::report::{Evidence, ValidationResult};
#[derive(Debug, Clone, Default, PartialEq)]
pub struct ValidationOutcome {
violations: Vec<ValidationResult>,
evidences: Vec<Evidence>,
}
impl ValidationOutcome {
pub fn new() -> Self {
Self::default()
}
pub fn from_violation(violation: ValidationResult) -> Self {
Self {
violations: vec![violation],
evidences: Vec::new(),
}
}
pub fn from_evidence(evidence: Evidence) -> Self {
Self {
violations: Vec::new(),
evidences: vec![evidence],
}
}
pub fn from_violations(violations: Vec<ValidationResult>) -> Self {
Self {
violations,
evidences: Vec::new(),
}
}
pub fn from_evidences(evidences: Vec<Evidence>) -> Self {
Self {
violations: Vec::new(),
evidences,
}
}
pub fn push_violation(&mut self, violation: ValidationResult) {
self.violations.push(violation);
}
pub fn push_evidence(&mut self, evidence: Evidence) {
self.evidences.push(evidence);
}
pub fn extend(&mut self, other: ValidationOutcome) {
self.violations.extend(other.violations);
self.evidences.extend(other.evidences);
}
pub fn conforms(&self) -> bool {
self.violations.is_empty()
}
pub fn is_empty(&self) -> bool {
self.violations.is_empty() && self.evidences.is_empty()
}
pub fn violations(&self) -> &[ValidationResult] {
&self.violations
}
pub fn evidences(&self) -> &[Evidence] {
&self.evidences
}
pub fn into_parts(self) -> (Vec<ValidationResult>, Vec<Evidence>) {
(self.violations, self.evidences)
}
}
impl FromIterator<ValidationOutcome> for ValidationOutcome {
fn from_iter<I: IntoIterator<Item = ValidationOutcome>>(iter: I) -> Self {
let mut acc = ValidationOutcome::new();
for outcome in iter {
acc.extend(outcome);
}
acc
}
}
impl Extend<ValidationOutcome> for ValidationOutcome {
fn extend<I: IntoIterator<Item = ValidationOutcome>>(&mut self, iter: I) {
for outcome in iter {
ValidationOutcome::extend(self, outcome);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::types::Severity;
use rudof_iri::IriS;
fn obj(s: &str) -> rudof_rdf::rdf_core::term::Object {
rudof_rdf::rdf_core::term::Object::iri(IriS::new_unchecked(s))
}
#[test]
fn empty_outcome_conforms() {
let outcome = ValidationOutcome::new();
assert!(outcome.conforms());
assert!(outcome.is_empty());
}
#[test]
fn outcome_with_violation_does_not_conform() {
let vr = ValidationResult::new(obj("http://ex/n"), obj("http://ex/c"), Severity::Violation);
let outcome = ValidationOutcome::from_violation(vr);
assert!(!outcome.conforms());
assert_eq!(outcome.violations().len(), 1);
}
#[test]
fn outcome_with_only_evidence_conforms() {
let ev = Evidence::new(obj("http://ex/n"), obj("http://ex/c"));
let outcome = ValidationOutcome::from_evidence(ev);
assert!(outcome.conforms());
assert_eq!(outcome.evidences().len(), 1);
}
#[test]
fn extend_merges_both_vectors() {
let vr = ValidationResult::new(obj("http://ex/n"), obj("http://ex/c"), Severity::Violation);
let ev = Evidence::new(obj("http://ex/n2"), obj("http://ex/c2"));
let mut a = ValidationOutcome::from_violation(vr);
let b = ValidationOutcome::from_evidence(ev);
a.extend(b);
assert_eq!(a.violations().len(), 1);
assert_eq!(a.evidences().len(), 1);
assert!(!a.conforms());
}
#[test]
fn from_iter_collects_across_outcomes() {
let outcomes = vec![
ValidationOutcome::from_evidence(Evidence::new(obj("http://ex/n1"), obj("http://ex/c"))),
ValidationOutcome::from_evidence(Evidence::new(obj("http://ex/n2"), obj("http://ex/c"))),
];
let acc: ValidationOutcome = outcomes.into_iter().collect();
assert_eq!(acc.evidences().len(), 2);
assert!(acc.conforms());
}
}