shex_ast/ast/
node_constraint.rs

1use std::fmt;
2
3use prefixmap::{Deref, DerefError, IriRef};
4// use log::debug;
5use serde::{
6    de::{self, MapAccess, Visitor},
7    Deserialize, Serialize, Serializer,
8};
9use srdf::numeric_literal::NumericLiteral;
10
11use super::ValueSetValue;
12use crate::{NodeKind, NumericFacet, Pattern, StringFacet, XsFacet};
13use serde::ser::SerializeMap;
14
15#[derive(Debug, Default, PartialEq, Clone)]
16pub struct NodeConstraint {
17    // #[serde(default, rename = "nodeKind", skip_serializing_if = "Option::is_none")]
18    node_kind: Option<NodeKind>,
19
20    // #[serde(default, skip_serializing_if = "Option::is_none")]
21    datatype: Option<IriRef>,
22
23    // #[serde(default, rename = "xsFacet", skip_serializing_if = "Option::is_none"]
24    xs_facet: Option<Vec<XsFacet>>,
25
26    // #[serde(default, skip_serializing_if = "Option::is_none")]
27    values: Option<Vec<ValueSetValue>>,
28}
29
30impl NodeConstraint {
31    pub fn new() -> Self {
32        Self::default()
33    }
34
35    pub fn with_datatype(mut self, datatype: IriRef) -> Self {
36        self.datatype = Some(datatype);
37        self
38    }
39
40    pub fn add_datatype(&mut self, datatype: IriRef) {
41        self.datatype = Some(datatype);
42    }
43
44    pub fn add_values(&mut self, values: Vec<ValueSetValue>) {
45        self.values = Some(values);
46    }
47
48    pub fn datatype(&self) -> Option<IriRef> {
49        self.datatype.clone()
50    }
51
52    pub fn with_node_kind(mut self, node_kind: NodeKind) -> Self {
53        self.node_kind = Some(node_kind);
54        self
55    }
56
57    pub fn node_kind(&self) -> Option<NodeKind> {
58        self.node_kind.clone()
59    }
60
61    pub fn with_xsfacets(mut self, facets: Vec<XsFacet>) -> Self {
62        self.xs_facet = if facets.is_empty() {
63            None
64        } else {
65            Some(facets)
66        };
67        self
68    }
69
70    pub fn with_pattern(mut self, pat: &str) -> Self {
71        match self.xs_facet {
72            Some(ref mut facets) => facets.push(XsFacet::pattern(pat)),
73            None => self.xs_facet = Some(vec![XsFacet::pattern(pat)]),
74        }
75        self
76    }
77
78    pub fn with_pattern_flags(mut self, pat: &str, flags: &str) -> Self {
79        match self.xs_facet {
80            Some(ref mut facets) => facets.push(XsFacet::pattern_flags(pat, flags)),
81            None => self.xs_facet = Some(vec![XsFacet::pattern_flags(pat, flags)]),
82        }
83        self
84    }
85
86    pub fn xs_facet(&self) -> Option<Vec<XsFacet>> {
87        self.xs_facet.clone()
88    }
89
90    pub fn with_length(self, len: usize) -> Self {
91        self.add_facet(XsFacet::length(len))
92    }
93
94    pub fn with_minlength(self, len: usize) -> Self {
95        self.add_facet(XsFacet::min_length(len))
96    }
97
98    pub fn with_maxlength(self, len: usize) -> Self {
99        self.add_facet(XsFacet::max_length(len))
100    }
101
102    pub fn with_min_inclusive(self, n: NumericLiteral) -> Self {
103        self.add_facet(XsFacet::min_inclusive(n))
104    }
105
106    pub fn with_max_inclusive(self, n: NumericLiteral) -> Self {
107        self.add_facet(XsFacet::max_inclusive(n))
108    }
109
110    pub fn add_facet(mut self, f: XsFacet) -> Self {
111        match self.xs_facet {
112            Some(ref mut facets) => facets.push(f),
113            None => self.xs_facet = Some(vec![f]),
114        }
115        self
116    }
117
118    pub fn with_min_exclusive(self, n: NumericLiteral) -> Self {
119        self.add_facet(XsFacet::min_exclusive(n))
120    }
121
122    pub fn with_max_exclusive(self, n: NumericLiteral) -> Self {
123        self.add_facet(XsFacet::max_exclusive(n))
124    }
125
126    pub fn with_totaldigits(self, n: usize) -> Self {
127        self.add_facet(XsFacet::totaldigits(n))
128    }
129
130    pub fn with_fractiondigits(self, n: usize) -> Self {
131        self.add_facet(XsFacet::fractiondigits(n))
132    }
133
134    pub fn with_values(mut self, values: Vec<ValueSetValue>) -> Self {
135        /*let mut vs: Vec<ValueSetValue> = Vec::with_capacity(values.len());
136        for v in values {
137            vs.push(v);
138        }*/
139        self.values = Some(values);
140        self
141    }
142
143    pub fn values(&self) -> Option<Vec<ValueSetValue>> {
144        match &self.values {
145            None => None,
146            Some(vs) => {
147                let mut r = Vec::new();
148                for v in vs {
149                    r.push((*v).clone())
150                }
151                Some(r)
152            }
153        }
154    }
155}
156
157impl Deref for NodeConstraint {
158    fn deref(
159        &self,
160        base: &Option<iri_s::IriS>,
161        prefixmap: &Option<prefixmap::PrefixMap>,
162    ) -> Result<Self, DerefError>
163    where
164        Self: Sized,
165    {
166        let datatype = <IriRef as Deref>::deref_opt(&self.datatype, base, prefixmap)?;
167        let values = <ValueSetValue as Deref>::deref_opt_vec(&self.values, base, prefixmap)?;
168        Ok(NodeConstraint {
169            node_kind: self.node_kind.clone(),
170            datatype,
171            xs_facet: self.xs_facet.clone(),
172            values,
173        })
174    }
175}
176
177impl Serialize for NodeConstraint {
178    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
179    where
180        S: Serializer,
181    {
182        let NodeConstraint {
183            node_kind,
184            datatype,
185            xs_facet,
186            values,
187        } = self;
188
189        let mut map = serializer.serialize_map(None)?;
190
191        // map.serialize_entry("type", "NodeConstraint")?;
192        match node_kind {
193            None => (),
194            Some(nk) => {
195                map.serialize_entry("nodeKind", &format!("{nk}").to_lowercase())?;
196            }
197        }
198        match datatype {
199            None => (),
200            Some(dt) => {
201                map.serialize_entry("datatype", &format!("{dt}"))?;
202            }
203        }
204        match values {
205            None => (),
206            Some(values) => {
207                map.serialize_entry("values", &values)?;
208            }
209        }
210        match xs_facet {
211            None => (),
212            Some(facets) => {
213                for f in facets {
214                    match f {
215                        XsFacet::StringFacet(sf) => match sf {
216                            StringFacet::Length(len) => map.serialize_entry("length", len)?,
217                            StringFacet::MinLength(ml) => map.serialize_entry("minlength", ml)?,
218                            StringFacet::MaxLength(ml) => map.serialize_entry("maxlength", ml)?,
219                            StringFacet::Pattern(Pattern { str, flags: None }) => {
220                                map.serialize_entry("pattern", str)?;
221                            }
222                            StringFacet::Pattern(Pattern {
223                                str,
224                                flags: Some(fs),
225                            }) => {
226                                map.serialize_entry("pattern", str)?;
227                                map.serialize_entry("flags", fs)?;
228                            }
229                        },
230                        XsFacet::NumericFacet(nf) => match nf {
231                            NumericFacet::FractionDigits(fd) => {
232                                map.serialize_entry("fractiondigits", fd)?
233                            }
234                            NumericFacet::TotalDigits(td) => {
235                                map.serialize_entry("totaldigits", td)?
236                            }
237                            NumericFacet::MaxExclusive(me) => {
238                                map.serialize_entry("maxexclusive", me)?
239                            }
240                            NumericFacet::MaxInclusive(mi) => {
241                                map.serialize_entry("maxinclusive", mi)?
242                            }
243                            NumericFacet::MinInclusive(mi) => {
244                                map.serialize_entry("mininclusive", mi)?
245                            }
246                            NumericFacet::MinExclusive(me) => {
247                                map.serialize_entry("minexclusive", me)?
248                            }
249                        },
250                    }
251                }
252            }
253        }
254        map.end()
255    }
256}
257
258impl<'de> Deserialize<'de> for NodeConstraint {
259    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
260    where
261        D: serde::Deserializer<'de>,
262    {
263        enum Field {
264            Type,
265            NodeKind,
266            Datatype,
267            Values,
268            Length,
269            MinLength,
270            MaxLength,
271            Pattern,
272            Flags,
273            MinInclusive,
274            MaxInclusive,
275            MinExclusive,
276            MaxExclusive,
277            TotalDigits,
278            FractionDigits,
279        }
280
281        impl<'de> Deserialize<'de> for Field {
282            fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
283            where
284                D: serde::Deserializer<'de>,
285            {
286                struct FieldVisitor;
287
288                impl Visitor<'_> for FieldVisitor {
289                    type Value = Field;
290
291                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
292                        formatter.write_str(
293                            "`type` or `nodeKind` or `datatype` or some xsfacet or `values` ",
294                        )
295                    }
296
297                    fn visit_str<E>(self, value: &str) -> Result<Field, E>
298                    where
299                        E: de::Error,
300                    {
301                        match value {
302                            "nodeKind" => Ok(Field::NodeKind),
303                            "datatype" => Ok(Field::Datatype),
304                            "type" => Ok(Field::Type),
305                            "pattern" => Ok(Field::Pattern),
306                            "flags" => Ok(Field::Flags),
307                            "length" => Ok(Field::Length),
308                            "minlength" => Ok(Field::MinLength),
309                            "maxlength" => Ok(Field::MaxLength),
310                            "mininclusive" => Ok(Field::MinInclusive),
311                            "maxinclusive" => Ok(Field::MaxInclusive),
312                            "minexclusive" => Ok(Field::MinExclusive),
313                            "maxexclusive" => Ok(Field::MaxExclusive),
314                            "totaldigits" => Ok(Field::TotalDigits),
315                            "fractiondigits" => Ok(Field::FractionDigits),
316                            "values" => Ok(Field::Values),
317                            _ => Err(de::Error::unknown_field(value, FIELDS)),
318                        }
319                    }
320                }
321
322                deserializer.deserialize_identifier(FieldVisitor)
323            }
324        }
325
326        struct NodeConstraintVisitor;
327
328        impl<'de> Visitor<'de> for NodeConstraintVisitor {
329            type Value = NodeConstraint;
330
331            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
332                formatter.write_str("struct NodeConstraint")
333            }
334
335            fn visit_map<V>(self, mut map: V) -> Result<NodeConstraint, V::Error>
336            where
337                V: MapAccess<'de>,
338            {
339                let mut type_: Option<String> = None;
340                let mut node_kind: Option<NodeKind> = None;
341                let mut datatype: Option<IriRef> = None;
342                let mut pattern: Option<String> = None;
343                let mut length: Option<usize> = None;
344                let mut minlength: Option<usize> = None;
345                let mut maxlength: Option<usize> = None;
346                let mut mininclusive: Option<NumericLiteral> = None;
347                let mut maxinclusive: Option<NumericLiteral> = None;
348                let mut minexclusive: Option<NumericLiteral> = None;
349                let mut maxexclusive: Option<NumericLiteral> = None;
350                let mut totaldigits: Option<usize> = None;
351                let mut fractiondigits: Option<usize> = None;
352                let mut flags: Option<String> = None;
353                let mut values: Option<Vec<ValueSetValue>> = None;
354                while let Some(key) = map.next_key()? {
355                    match key {
356                        Field::NodeKind => {
357                            if node_kind.is_some() {
358                                return Err(de::Error::duplicate_field("nodeKind"));
359                            }
360                            let value = map.next_value()?;
361                            node_kind = match value {
362                                "iri" => Some(NodeKind::Iri),
363                                "bnode" => Some(NodeKind::BNode),
364                                "literal" => Some(NodeKind::Literal),
365                                "nonliteral" => Some(NodeKind::NonLiteral),
366                                _ => {
367                                    return Err(de::Error::custom(format!(
368                                        "Unexpected value for `nodeKind`: {value}"
369                                    )))
370                                }
371                            }
372                        }
373                        Field::Datatype => {
374                            if datatype.is_some() {
375                                return Err(de::Error::duplicate_field("datatype"));
376                            }
377                            let iri: IriRef = map.next_value()?;
378                            datatype = Some(iri);
379                        }
380                        Field::Values => {
381                            if values.is_some() {
382                                return Err(de::Error::duplicate_field("values"));
383                            }
384                            let vs: Vec<ValueSetValue> = map.next_value()?;
385                            values = Some(vs)
386                        }
387                        Field::Pattern => {
388                            if pattern.is_some() {
389                                return Err(de::Error::duplicate_field("pattern"));
390                            }
391                            pattern = Some(map.next_value()?);
392                        }
393                        Field::Length => {
394                            if length.is_some() {
395                                return Err(de::Error::duplicate_field("length"));
396                            }
397                            length = Some(map.next_value()?);
398                        }
399                        Field::MinLength => {
400                            if minlength.is_some() {
401                                return Err(de::Error::duplicate_field("minlength"));
402                            }
403                            minlength = Some(map.next_value()?);
404                        }
405                        Field::MaxLength => {
406                            if maxlength.is_some() {
407                                return Err(de::Error::duplicate_field("maxlength"));
408                            }
409                            maxlength = Some(map.next_value()?);
410                        }
411                        Field::MinInclusive => {
412                            if mininclusive.is_some() {
413                                return Err(de::Error::duplicate_field("mininclusive"));
414                            }
415                            mininclusive = Some(map.next_value()?);
416                        }
417                        Field::MaxInclusive => {
418                            if maxinclusive.is_some() {
419                                return Err(de::Error::duplicate_field("maxinclusive"));
420                            }
421                            maxinclusive = Some(map.next_value()?);
422                        }
423                        Field::MinExclusive => {
424                            if minexclusive.is_some() {
425                                return Err(de::Error::duplicate_field("minexclusive"));
426                            }
427                            minexclusive = Some(map.next_value()?);
428                        }
429                        Field::MaxExclusive => {
430                            if maxexclusive.is_some() {
431                                return Err(de::Error::duplicate_field("maxexclusive"));
432                            }
433                            maxexclusive = Some(map.next_value()?);
434                        }
435                        Field::TotalDigits => {
436                            if totaldigits.is_some() {
437                                return Err(de::Error::duplicate_field("totaldigits"));
438                            }
439                            totaldigits = Some(map.next_value()?);
440                        }
441                        Field::FractionDigits => {
442                            if fractiondigits.is_some() {
443                                return Err(de::Error::duplicate_field("fractiondigits"));
444                            }
445                            fractiondigits = Some(map.next_value()?);
446                        }
447                        Field::Type => {
448                            if type_.is_some() {
449                                return Err(de::Error::duplicate_field("type"));
450                            }
451                            let value: String = map.next_value()?;
452                            if value != "NodeConstraint" {
453                                return Err(de::Error::custom(format!(
454                                    "Expected NodeConstraint, found: {value}"
455                                )));
456                            }
457                            type_ = Some("NodeConstraint".to_string());
458                        }
459                        Field::Flags => {
460                            if flags.is_some() {
461                                return Err(de::Error::duplicate_field("flags"));
462                            }
463                            flags = Some(map.next_value()?);
464                        }
465                    }
466                }
467                let mut nc = NodeConstraint::new();
468                if let Some(nk) = node_kind {
469                    nc = nc.with_node_kind(nk)
470                }
471                if let Some(pat) = pattern {
472                    if let Some(flags) = flags {
473                        nc = nc.with_pattern_flags(&pat, &flags)
474                    } else {
475                        nc = nc.with_pattern(&pat)
476                    }
477                }
478                if let Some(length) = length {
479                    nc = nc.with_length(length)
480                }
481                if let Some(datatype) = datatype {
482                    nc = nc.with_datatype(datatype)
483                }
484                if let Some(vs) = values {
485                    nc = nc.with_values(vs)
486                }
487                if let Some(minlength) = minlength {
488                    nc = nc.with_minlength(minlength)
489                }
490                if let Some(maxlength) = maxlength {
491                    nc = nc.with_maxlength(maxlength)
492                }
493                if let Some(mininclusive) = mininclusive {
494                    nc = nc.with_min_inclusive(mininclusive)
495                }
496                if let Some(maxinclusive) = maxinclusive {
497                    nc = nc.with_max_inclusive(maxinclusive)
498                }
499                if let Some(minexclusive) = minexclusive {
500                    nc = nc.with_min_exclusive(minexclusive)
501                }
502                if let Some(maxexclusive) = maxexclusive {
503                    nc = nc.with_max_exclusive(maxexclusive)
504                }
505                if let Some(totaldigits) = totaldigits {
506                    nc = nc.with_totaldigits(totaldigits)
507                }
508                if let Some(fractiondigits) = fractiondigits {
509                    nc = nc.with_fractiondigits(fractiondigits)
510                }
511                Ok(nc)
512            }
513        }
514
515        const FIELDS: &[&str] = &[
516            "type",
517            "nodeKind",
518            "datatype",
519            "values",
520            "pattern",
521            "flags",
522            "length",
523            "minlength",
524            "maxlength",
525            "mininclusive",
526            "maxinclusive",
527            "minexclusive",
528            "maxexclusive",
529            "totaldigits",
530            "fractiondigits",
531        ];
532        deserializer.deserialize_struct("NodeConstraint", FIELDS, NodeConstraintVisitor)
533    }
534}
535
536#[cfg(test)]
537mod tests {
538    use super::*;
539
540    #[test]
541    fn test_serialize_node_kind_iri() {
542        let nc = NodeConstraint::new().with_node_kind(NodeKind::Iri);
543        let json_nc = serde_json::to_string(&nc).unwrap();
544        assert_eq!(json_nc, "{\"nodeKind\":\"iri\"}");
545    }
546
547    #[test]
548    fn test_deserialize_node_kind_iri() {
549        let str = r#"{ "type":"NodeConstraint","nodeKind": "iri"}"#;
550        let deserialized: NodeConstraint = serde_json::from_str(str).unwrap();
551        let expected = NodeConstraint::new().with_node_kind(NodeKind::Iri);
552        assert_eq!(deserialized, expected);
553    }
554
555    #[test]
556    fn test_serialize_pattern() {
557        let nc = NodeConstraint::new().with_pattern("o*");
558        let json_nc = serde_json::to_string(&nc).unwrap();
559        let expected = r#"{"pattern":"o*"}"#;
560        assert_eq!(json_nc, expected);
561    }
562
563    #[test]
564    fn test_deserialize_pattern() {
565        let str = r#"{ "type":"NodeConstraint","pattern": "o*"}"#;
566        let deserialized: NodeConstraint = serde_json::from_str(str).unwrap();
567        let expected = NodeConstraint::new().with_pattern("o*");
568        assert_eq!(deserialized, expected);
569    }
570
571    #[test]
572    fn test_serialize_pattern_flags() {
573        let nc = NodeConstraint::new().with_pattern_flags("o*", "i");
574        let json_nc = serde_json::to_string(&nc).unwrap();
575        let expected = r#"{"pattern":"o*","flags":"i"}"#;
576        assert_eq!(json_nc, expected);
577    }
578    #[test]
579    fn test_deserialize_pattern_flags() {
580        let str = r#"{ "type":"NodeConstraint","pattern": "o*", "flags": "i"}"#;
581        let deserialized: NodeConstraint = serde_json::from_str(str).unwrap();
582        let expected = NodeConstraint::new().with_pattern_flags("o*", "i");
583        assert_eq!(deserialized, expected);
584    }
585}