use crate::types::{NodeKind, Value};
use itertools::Itertools;
use prefixmap::IriRef;
use rudof_iri::IriS;
use rudof_rdf::rdf_core::term::Object;
use rudof_rdf::rdf_core::term::literal::{ConcreteLiteral, Lang};
use rudof_rdf::rdf_core::vocabs::ShaclVocab;
use std::collections::HashSet;
use std::fmt::{Display, Formatter};
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum ASTComponent {
Class(Object),
Datatype(IriRef),
NodeKind(NodeKind),
MinCount(isize),
MaxCount(isize),
MinExclusive(ConcreteLiteral),
MaxExclusive(ConcreteLiteral),
MinInclusive(ConcreteLiteral),
MaxInclusive(ConcreteLiteral),
MinLength(isize),
MaxLength(isize),
Pattern {
pattern: String,
flags: Option<String>,
},
UniqueLang(bool),
LanguageIn(Vec<Lang>),
Equals(IriRef),
Disjoint(IriRef),
LessThan(IriRef),
LessThanOrEquals(IriRef),
Or(Vec<Object>),
And(Vec<Object>),
Not(Object),
Xone(Vec<Object>),
Closed {
is_closed: bool,
ignored_properties: HashSet<IriS>,
},
Node(Object),
HasValue(Value),
In(Vec<Value>),
QualifiedValueShape {
shape: Object,
q_min_count: Option<isize>,
q_max_count: Option<isize>,
disjoint: Option<bool>,
siblings: Vec<Object>,
},
Deactivated(bool), }
impl Display for ASTComponent {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ASTComponent::Class(o) => write!(f, "class({o})"),
ASTComponent::Datatype(iri) => write!(f, "datatype({iri})"),
ASTComponent::NodeKind(node) => write!(f, "nodeKind({node})"),
ASTComponent::MinCount(qty) => write!(f, "minCount({qty})"),
ASTComponent::MaxCount(qty) => write!(f, "maxCount({qty})"),
ASTComponent::MinExclusive(lit) => write!(f, "minExclusive({lit})"),
ASTComponent::MaxExclusive(lit) => write!(f, "maxExclusive({lit})"),
ASTComponent::MinInclusive(lit) => write!(f, "minInclusive({lit})"),
ASTComponent::MaxInclusive(lit) => write!(f, "maxInclusive({lit})"),
ASTComponent::MinLength(l) => write!(f, "minLength({l})"),
ASTComponent::MaxLength(l) => write!(f, "maxLength({l})"),
ASTComponent::Pattern { pattern, flags } => match flags {
None => write!(f, "pattern({pattern})"),
Some(flags) => write!(f, "pattern({pattern}, {flags})"),
},
ASTComponent::UniqueLang(l) => write!(f, "uniqueLang({l})"),
ASTComponent::LanguageIn(l) => {
let str = l.iter().map(|s| s.to_string()).join(", ");
write!(f, "languageIn[{str}]")
},
ASTComponent::Equals(iri) => write!(f, "equals({iri})"),
ASTComponent::Disjoint(iri) => write!(f, "disjoint({iri})"),
ASTComponent::LessThan(iri) => write!(f, "lessThan({iri})"),
ASTComponent::LessThanOrEquals(iri) => write!(f, "lessThanOrEquals({iri})"),
ASTComponent::Or(obj) => {
let str = obj.iter().map(|s| s.to_string()).join(", ");
write!(f, "or[{str}]")
},
ASTComponent::And(obj) => {
let str = obj.iter().map(|s| s.to_string()).join(", ");
write!(f, "and[{str}]")
},
ASTComponent::Not(obj) => write!(f, "not({obj})"),
ASTComponent::Xone(obj) => {
let str = obj.iter().map(|s| s.to_string()).join(", ");
write!(f, "xone[{str}]")
},
ASTComponent::Closed {
is_closed,
ignored_properties,
} => write!(
f,
"closed({is_closed}{})",
if ignored_properties.is_empty() {
"".to_string()
} else {
format!(
", Ignored props: [{}]",
ignored_properties.iter().map(|p| p.to_string()).join(", ")
)
}
),
ASTComponent::Node(obj) => write!(f, "node({obj})"),
ASTComponent::HasValue(v) => write!(f, "hasValue({v})"),
ASTComponent::In(v) => {
let str = v.iter().map(|v| v.to_string()).join(", ");
write!(f, "in[{str}]")
},
ASTComponent::QualifiedValueShape {
shape,
disjoint,
siblings,
q_max_count,
q_min_count,
} => {
write!(
f,
"qualifiedValueShape(shape: {shape}, qualified_min_count: {q_min_count:?}, qualified_max_count: {q_max_count:?}, qualified_value_shape_disjoint: {disjoint:?}{}",
if siblings.is_empty() {
"".to_string()
} else {
format!(", siblings: [{}]", siblings.iter().map(|s| s.to_string()).join(", "))
}
)
},
ASTComponent::Deactivated(b) => write!(f, "deactivated({b})"),
}
}
}
impl From<ASTComponent> for IriS {
fn from(value: ASTComponent) -> Self {
match value {
ASTComponent::Class(_) => ShaclVocab::sh_class(),
ASTComponent::Datatype(_) => ShaclVocab::sh_datatype(),
ASTComponent::NodeKind(_) => ShaclVocab::sh_node_kind(),
ASTComponent::MinCount(_) => ShaclVocab::sh_min_count(),
ASTComponent::MaxCount(_) => ShaclVocab::sh_max_count(),
ASTComponent::MinExclusive(_) => ShaclVocab::sh_min_exclusive(),
ASTComponent::MaxExclusive(_) => ShaclVocab::sh_max_exclusive(),
ASTComponent::MinInclusive(_) => ShaclVocab::sh_min_inclusive(),
ASTComponent::MaxInclusive(_) => ShaclVocab::sh_max_inclusive(),
ASTComponent::MinLength(_) => ShaclVocab::sh_min_length(),
ASTComponent::MaxLength(_) => ShaclVocab::sh_max_length(),
ASTComponent::Pattern { .. } => ShaclVocab::sh_pattern(),
ASTComponent::UniqueLang(_) => ShaclVocab::sh_unique_lang(),
ASTComponent::LanguageIn(_) => ShaclVocab::sh_language_in(),
ASTComponent::Equals(_) => ShaclVocab::sh_equals(),
ASTComponent::Disjoint(_) => ShaclVocab::sh_disjoint(),
ASTComponent::LessThan(_) => ShaclVocab::sh_less_than(),
ASTComponent::LessThanOrEquals(_) => ShaclVocab::sh_less_than_or_equals(),
ASTComponent::Or(_) => ShaclVocab::sh_or(),
ASTComponent::And(_) => ShaclVocab::sh_and(),
ASTComponent::Not(_) => ShaclVocab::sh_not(),
ASTComponent::Xone(_) => ShaclVocab::sh_xone(),
ASTComponent::Closed { .. } => ShaclVocab::sh_closed(),
ASTComponent::Node(_) => ShaclVocab::sh_node(),
ASTComponent::HasValue(_) => ShaclVocab::sh_has_value(),
ASTComponent::In(_) => ShaclVocab::sh_in(),
ASTComponent::QualifiedValueShape { .. } => ShaclVocab::sh_qualified_value_shape(),
ASTComponent::Deactivated(_) => ShaclVocab::sh_deactivated(),
}
}
}