1use std::fmt;
2
3use prefixmap::{Deref, DerefError, IriRef};
4use 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 node_kind: Option<NodeKind>,
19
20 datatype: Option<IriRef>,
22
23 xs_facet: Option<Vec<XsFacet>>,
25
26 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 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 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}