use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "camelCase")]
pub enum ShaclConstraint {
MinCount(usize),
MaxCount(usize),
Datatype(String),
Pattern(String),
MinInclusive(f64),
MaxInclusive(f64),
Class(String),
NodeKind(NodeKind),
In(Vec<String>),
HasValue(String),
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum NodeKind {
Iri,
Literal,
BlankNode,
BlankNodeOrIri,
BlankNodeOrLiteral,
IriOrLiteral,
}
impl std::str::FromStr for NodeKind {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"IRI" | "sh:IRI" => Ok(Self::Iri),
"Literal" | "sh:Literal" => Ok(Self::Literal),
"BlankNode" | "sh:BlankNode" => Ok(Self::BlankNode),
"BlankNodeOrIRI" | "sh:BlankNodeOrIRI" => Ok(Self::BlankNodeOrIri),
"BlankNodeOrLiteral" | "sh:BlankNodeOrLiteral" => Ok(Self::BlankNodeOrLiteral),
"IRIOrLiteral" | "sh:IRIOrLiteral" => Ok(Self::IriOrLiteral),
_ => Err(format!("unknown NodeKind: {s:?}")),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PropertyShape {
pub path: String,
pub name: Option<String>,
pub constraints: Vec<ShaclConstraint>,
}
impl PropertyShape {
pub fn new(path: impl Into<String>) -> Self {
Self {
path: path.into(),
name: None,
constraints: Vec::new(),
}
}
pub fn with_constraint(mut self, c: ShaclConstraint) -> Self {
self.constraints.push(c);
self
}
pub fn named(mut self, name: impl Into<String>) -> Self {
self.name = Some(name.into());
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeShape {
pub id: String,
pub target_class: Option<String>,
pub target_node: Option<String>,
pub properties: Vec<PropertyShape>,
pub closed: bool,
}
impl NodeShape {
pub fn new(id: impl Into<String>) -> Self {
Self {
id: id.into(),
target_class: None,
target_node: None,
properties: Vec::new(),
closed: false,
}
}
pub fn targeting_class(mut self, class: impl Into<String>) -> Self {
self.target_class = Some(class.into());
self
}
pub fn with_property(mut self, prop: PropertyShape) -> Self {
self.properties.push(prop);
self
}
pub fn closed(mut self) -> Self {
self.closed = true;
self
}
}