use prefixmap::error::DerefError;
use prefixmap::{DerefIri, IriRef, PrefixMap};
use rudof_iri::IriS;
use serde::{Deserialize, Serialize, Serializer};
use std::str::FromStr;
use super::serde_string_or_struct::SerializeStringOrStruct;
use crate::Annotation;
use crate::ast::serde_string_or_struct::*;
use crate::{NodeConstraint, RefError, Shape, ShapeExprLabel};
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
#[serde(transparent)]
pub struct ShapeExprWrapper {
#[serde(
serialize_with = "serialize_string_or_struct",
deserialize_with = "deserialize_string_or_struct"
)]
pub se: ShapeExpr,
}
impl DerefIri for ShapeExprWrapper {
fn deref_iri(self, base: Option<&IriS>, prefixmap: Option<&PrefixMap>) -> Result<Self, DerefError> {
let se = self.se.deref_iri(base, prefixmap)?;
let sew = ShapeExprWrapper { se };
Ok(sew)
}
}
impl From<ShapeExpr> for ShapeExprWrapper {
fn from(shape_expr: ShapeExpr) -> Self {
Self { se: shape_expr }
}
}
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
#[serde(tag = "type")]
pub enum ShapeExpr {
ShapeOr {
#[serde(rename = "shapeExprs")]
shape_exprs: Vec<ShapeExprWrapper>,
},
ShapeAnd {
#[serde(rename = "shapeExprs")]
shape_exprs: Vec<ShapeExprWrapper>,
},
ShapeNot {
#[serde(rename = "shapeExpr")]
shape_expr: Box<ShapeExprWrapper>,
},
NodeConstraint(NodeConstraint),
Shape(Shape),
#[serde(rename = "ShapeExternal")]
External,
Ref(ShapeExprLabel),
}
impl FromStr for ShapeExpr {
type Err = RefError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let ref_ = ShapeExprLabel::from_str(s)?;
Ok(ShapeExpr::Ref(ref_))
}
}
impl SerializeStringOrStruct for ShapeExpr {
fn serialize_string_or_struct<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match &self {
ShapeExpr::Ref(r) => r.serialize(serializer),
_ => self.serialize(serializer),
}
}
}
impl ShapeExpr {
pub fn empty_shape() -> ShapeExpr {
ShapeExpr::Shape(Shape::default())
}
pub fn external() -> ShapeExpr {
ShapeExpr::External
}
pub fn shape_not(se: ShapeExpr) -> ShapeExpr {
ShapeExpr::ShapeNot {
shape_expr: Box::new(ShapeExprWrapper { se }),
}
}
pub fn or(ses: Vec<ShapeExpr>) -> ShapeExpr {
let mut shape_exprs = Vec::new();
for se in ses {
shape_exprs.push(se.into())
}
ShapeExpr::ShapeOr { shape_exprs }
}
pub fn and(ses: Vec<ShapeExpr>) -> ShapeExpr {
let mut shape_exprs = Vec::new();
for se in ses {
shape_exprs.push(se.into())
}
ShapeExpr::ShapeAnd { shape_exprs }
}
pub fn node_constraint(nc: NodeConstraint) -> ShapeExpr {
ShapeExpr::NodeConstraint(nc)
}
pub fn iri_ref(iri_ref: IriRef) -> ShapeExpr {
ShapeExpr::Ref(ShapeExprLabel::iri_ref(iri_ref))
}
pub fn shape_ref(label: ShapeExprLabel) -> ShapeExpr {
ShapeExpr::Ref(label)
}
pub fn any() -> ShapeExpr {
ShapeExpr::default()
}
pub fn shape(shape: Shape) -> ShapeExpr {
ShapeExpr::Shape(shape)
}
pub fn add_annotation(&mut self, annotation: Annotation) {
match self {
Self::Shape(s) => s.add_annotation(annotation),
_ => todo!(),
};
}
pub fn has_annotations(&self) -> bool {
match self {
Self::Shape(s) => s.has_annotations(),
_ => todo!(),
}
}
pub fn annotations(&self) -> Option<impl Iterator<Item = &Annotation>> {
match self {
Self::Shape(s) => s.annotations(),
_ => todo!(),
}
}
pub fn is_ref(&self) -> bool {
matches!(self, Self::Ref(_))
}
pub fn is_datatype(&self) -> bool {
matches!(self, Self::NodeConstraint(nc) if nc.is_datatype())
}
}
impl Default for ShapeExpr {
fn default() -> Self {
ShapeExpr::Shape(Shape::default())
}
}
impl DerefIri for ShapeExpr {
fn deref_iri(self, base: Option<&IriS>, prefixmap: Option<&PrefixMap>) -> Result<Self, DerefError> {
match self {
ShapeExpr::External => Ok(ShapeExpr::External),
ShapeExpr::ShapeAnd { shape_exprs } => {
let shape_exprs = shape_exprs.deref_iri(base, prefixmap)?;
Ok(ShapeExpr::ShapeAnd {
shape_exprs: shape_exprs.clone(),
})
},
ShapeExpr::ShapeOr { shape_exprs } => {
let shape_exprs = shape_exprs.deref_iri(base, prefixmap)?;
Ok(ShapeExpr::ShapeOr {
shape_exprs: shape_exprs.clone(),
})
},
ShapeExpr::ShapeNot { shape_expr } => Ok(ShapeExpr::ShapeNot {
shape_expr: shape_expr.deref_iri(base, prefixmap)?,
}),
ShapeExpr::Shape(shape) => {
let shape = shape.deref_iri(base, prefixmap)?;
Ok(ShapeExpr::Shape(shape))
},
ShapeExpr::Ref(ref_) => {
let ref_ = ref_.deref_iri(base, prefixmap)?;
Ok(ShapeExpr::Ref(ref_))
},
ShapeExpr::NodeConstraint(nc) => {
let nc = nc.deref_iri(base, prefixmap)?;
Ok(ShapeExpr::NodeConstraint(nc))
},
}
}
}
#[cfg(test)]
mod tests {
use crate::{Pattern, StringFacet, XsFacet};
use super::*;
#[test]
fn test_serde_xsfacet_pattern() {
let facets: Vec<XsFacet> = vec![XsFacet::StringFacet(StringFacet::Pattern(Pattern::new("o*")))];
let nc = NodeConstraint::new().with_xsfacets(facets);
let se = ShapeExpr::NodeConstraint(nc);
let json_nc = serde_json::to_string(&se).unwrap();
assert_eq!(json_nc, "{\"type\":\"NodeConstraint\",\"pattern\":\"o*\"}");
}
}