shex_ast/ir/
ast2ir.rs

1use std::collections::HashMap;
2
3use crate::ir::annotation::Annotation;
4use crate::ir::object_value::ObjectValue;
5use crate::ir::schema_ir::SchemaIR;
6use crate::ir::sem_act::SemAct;
7use crate::ir::shape::Shape;
8use crate::ir::shape_expr::ShapeExpr;
9use crate::ir::shape_label::ShapeLabel;
10use crate::ir::value_set::ValueSet;
11use crate::ir::value_set_value::ValueSetValue;
12use crate::ShapeExprLabel;
13use crate::{ast, ast::Schema as SchemaJson, SchemaIRError, ShapeLabelIdx};
14use crate::{CResult, Cond, Node, Pred};
15use iri_s::IriS;
16use lazy_static::lazy_static;
17use prefixmap::IriRef;
18use rbe::{rbe::Rbe, Component, MatchCond, Max, Min, RbeTable};
19use rbe::{Cardinality, Pending, RbeError, SingleCond};
20use srdf::literal::Literal;
21use srdf::Object;
22use tracing::debug;
23
24use super::node_constraint::NodeConstraint;
25
26lazy_static! {
27    static ref XSD_STRING: IriRef = IriRef::Iri(IriS::new_unchecked(
28        "http://www.w3.org/2001/XMLSchema#string"
29    ));
30    static ref RDF_LANG_STRING: IriRef = IriRef::Iri(IriS::new_unchecked(
31        "http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
32    ));
33}
34
35#[derive(Debug, Default)]
36/// AST2IR compile a Schema in AST (JSON) to IR (Intermediate Representation).
37pub struct AST2IR {
38    shape_decls_counter: usize,
39}
40
41impl AST2IR {
42    pub fn new() -> Self {
43        Self::default()
44    }
45
46    pub fn compile(
47        &mut self,
48        schema_json: &SchemaJson,
49        compiled_schema: &mut SchemaIR,
50    ) -> CResult<()> {
51        debug!("Compiling schema_json: {compiled_schema:?}");
52        compiled_schema.set_prefixmap(schema_json.prefixmap());
53        self.collect_shape_labels(schema_json, compiled_schema)?;
54        self.collect_shape_exprs(schema_json, compiled_schema)?;
55        Ok(())
56    }
57
58    pub fn collect_shape_labels(
59        &mut self,
60        schema_json: &SchemaJson,
61        compiled_schema: &mut SchemaIR,
62    ) -> CResult<()> {
63        match &schema_json.shapes() {
64            None => Ok(()),
65            Some(sds) => {
66                for sd in sds {
67                    let label = self.shape_expr_label_to_shape_label(&sd.id)?;
68                    compiled_schema.add_shape(label, ShapeExpr::Empty);
69                    self.shape_decls_counter += 1;
70                }
71                Ok(())
72            }
73        }
74    }
75
76    pub fn collect_shape_exprs(
77        &mut self,
78        schema_json: &SchemaJson,
79        compiled_schema: &mut SchemaIR,
80    ) -> CResult<()> {
81        match &schema_json.shapes() {
82            None => Ok(()),
83            Some(sds) => {
84                for sd in sds {
85                    let idx = self.get_shape_label_idx(&sd.id, compiled_schema)?;
86                    let se = self.compile_shape_decl(sd, &idx, compiled_schema)?;
87                    compiled_schema.replace_shape(&idx, se)
88                }
89                Ok(())
90            }
91        }
92    }
93
94    fn shape_expr_label_to_shape_label(&self, id: &ShapeExprLabel) -> CResult<ShapeLabel> {
95        match id {
96            ShapeExprLabel::IriRef { value } => {
97                let shape_label = iri_ref_2_shape_label(value)?;
98                Ok(shape_label)
99            }
100            ShapeExprLabel::BNode { value } => Ok(ShapeLabel::BNode(value.clone())),
101            ShapeExprLabel::Start => Ok(ShapeLabel::Start),
102        }
103    }
104
105    fn get_shape_label_idx(
106        &self,
107        id: &ShapeExprLabel,
108        compiled_schema: &mut SchemaIR,
109    ) -> CResult<ShapeLabelIdx> {
110        let label = self.shape_expr_label_to_shape_label(id)?;
111        compiled_schema.get_shape_label_idx(&label)
112    }
113
114    fn compile_shape_decl(
115        &self,
116        sd: &ast::ShapeDecl,
117        idx: &ShapeLabelIdx,
118        compiled_schema: &mut SchemaIR,
119    ) -> CResult<ShapeExpr> {
120        self.compile_shape_expr(&sd.shape_expr, idx, compiled_schema)
121    }
122
123    fn ref2idx(
124        &self,
125        sref: &ast::ShapeExprLabel,
126        compiled_schema: &mut SchemaIR,
127    ) -> CResult<ShapeLabelIdx> {
128        let idx = self.get_shape_label_idx(sref, compiled_schema)?;
129        Ok(idx)
130    }
131
132    fn compile_shape_expr(
133        &self,
134        se: &ast::ShapeExpr,
135        idx: &ShapeLabelIdx,
136        compiled_schema: &mut SchemaIR,
137    ) -> CResult<ShapeExpr> {
138        let result: ShapeExpr = match se {
139            ast::ShapeExpr::Ref(se_ref) => {
140                let new_idx = self.ref2idx(se_ref, compiled_schema)?;
141                let se: ShapeExpr = ShapeExpr::Ref { idx: new_idx };
142                Ok::<ShapeExpr, SchemaIRError>(se)
143            }
144            ast::ShapeExpr::ShapeOr { shape_exprs: ses } => {
145                let mut cnv = Vec::new();
146                for sew in ses {
147                    let se = self.compile_shape_expr(&sew.se, idx, compiled_schema)?;
148                    cnv.push(se);
149                }
150                let display = match compiled_schema.find_shape_idx(idx) {
151                    None => "internal OR".to_string(),
152                    Some((Some(label), _)) => compiled_schema.show_label(label),
153                    Some((None, _)) => "internal OR with some se".to_string(),
154                };
155
156                Ok(ShapeExpr::ShapeOr {
157                    exprs: cnv,
158                    display,
159                })
160            }
161            ast::ShapeExpr::ShapeAnd { shape_exprs: ses } => {
162                let mut cnv = Vec::new();
163                for sew in ses {
164                    let se = self.compile_shape_expr(&sew.se, idx, compiled_schema)?;
165                    cnv.push(se);
166                }
167                let display = match compiled_schema.find_shape_idx(idx) {
168                    None => "internal AND".to_string(),
169                    Some((Some(label), _)) => compiled_schema.show_label(label),
170                    Some((None, _)) => "internal AND with some se".to_string(),
171                };
172                Ok(ShapeExpr::ShapeAnd {
173                    exprs: cnv,
174                    display,
175                })
176            }
177            ast::ShapeExpr::ShapeNot { shape_expr: sew } => {
178                let se = self.compile_shape_expr(&sew.se, idx, compiled_schema)?;
179                let display = match compiled_schema.find_shape_idx(idx) {
180                    None => "internal NOT".to_string(),
181                    Some((Some(label), _)) => compiled_schema.show_label(label),
182                    Some((None, _)) => "internal NOT with some shape expr".to_string(),
183                };
184                Ok(ShapeExpr::ShapeNot {
185                    expr: Box::new(se),
186                    display,
187                })
188            }
189            ast::ShapeExpr::Shape(shape) => {
190                let new_extra = self.cnv_extra(&shape.extra)?;
191                let rbe_table = match &shape.expression {
192                    None => RbeTable::new(),
193                    Some(tew) => {
194                        let mut table = RbeTable::new();
195                        let rbe = self.triple_expr2rbe(&tew.te, compiled_schema, &mut table)?;
196                        table.with_rbe(rbe);
197                        table
198                    }
199                };
200                let preds = Self::get_preds_shape(shape);
201                let references = self.get_references_shape(shape, compiled_schema);
202
203                let display = match compiled_schema.find_shape_idx(idx) {
204                    None => "internal".to_string(),
205                    Some((Some(label), _)) => compiled_schema.show_label(label),
206                    Some((None, _)) => "internal with shape expr:".to_string(),
207                };
208
209                let shape = Shape::new(
210                    Self::cnv_closed(&shape.closed),
211                    new_extra,
212                    rbe_table,
213                    Self::cnv_sem_acts(&shape.sem_acts),
214                    Self::cnv_annotations(&shape.annotations),
215                    preds,
216                    references,
217                    display,
218                );
219                Ok(ShapeExpr::Shape(shape))
220            }
221            ast::ShapeExpr::NodeConstraint(nc) => {
222                let cond = Self::cnv_node_constraint(
223                    self,
224                    &nc.node_kind(),
225                    &nc.datatype(),
226                    &nc.xs_facet(),
227                    &nc.values(),
228                )?;
229                let display = match compiled_schema.find_shape_idx(idx) {
230                    None => "internal NodeConstraint".to_string(),
231                    Some((Some(label), _)) => compiled_schema.show_label(label),
232                    Some((None, _)) => "internal NodeConstraint with some shape expr".to_string(),
233                };
234                let node_constraint = NodeConstraint::new(nc.clone(), cond, display);
235                Ok(ShapeExpr::NodeConstraint(node_constraint))
236            }
237            ast::ShapeExpr::External => Ok(ShapeExpr::External {}),
238        }?;
239        //compiled_schema.replace_shape(idx, result.clone());
240        // println!("Replacing {idx} with {result}");
241        Ok(result)
242    }
243
244    fn cnv_node_constraint(
245        &self,
246        nk: &Option<ast::NodeKind>,
247        dt: &Option<IriRef>,
248        xs_facet: &Option<Vec<ast::XsFacet>>,
249        values: &Option<Vec<ast::ValueSetValue>>,
250    ) -> CResult<Cond> {
251        let maybe_value_set = match values {
252            Some(vs) => {
253                let value_set = create_value_set(vs)?;
254                Some(value_set)
255            }
256            None => None,
257        };
258        node_constraint2match_cond(nk, dt, xs_facet, &maybe_value_set)
259    }
260
261    fn cnv_closed(closed: &Option<bool>) -> bool {
262        match closed {
263            None => false,
264            Some(closed) => *closed,
265        }
266    }
267
268    fn cnv_extra(&self, extra: &Option<Vec<IriRef>>) -> CResult<Vec<Pred>> {
269        if let Some(extra) = extra {
270            let mut vs = Vec::new();
271            for iri in extra {
272                let nm = cnv_iri_ref(iri)?;
273                vs.push(Pred::new(nm));
274            }
275            Ok(vs)
276        } else {
277            Ok(Vec::new())
278        }
279    }
280
281    fn cnv_sem_acts(sem_acts: &Option<Vec<ast::SemAct>>) -> Vec<SemAct> {
282        if let Some(_vs) = sem_acts {
283            // TODO
284            Vec::new()
285        } else {
286            Vec::new()
287        }
288    }
289
290    fn cnv_annotations(annotations: &Option<Vec<ast::Annotation>>) -> Vec<Annotation> {
291        if let Some(_anns) = annotations {
292            // TODO
293            Vec::new()
294        } else {
295            Vec::new()
296        }
297    }
298
299    fn triple_expr2rbe(
300        &self,
301        triple_expr: &ast::TripleExpr,
302        compiled_schema: &mut SchemaIR,
303        current_table: &mut RbeTable<Pred, Node, ShapeLabelIdx>,
304    ) -> CResult<Rbe<Component>> {
305        match triple_expr {
306            ast::TripleExpr::EachOf {
307                id: _,
308                expressions,
309                min,
310                max,
311                sem_acts: _,
312                annotations: _,
313            } => {
314                let mut cs = Vec::new();
315                for e in expressions {
316                    let c = self.triple_expr2rbe(&e.te, compiled_schema, current_table)?;
317                    cs.push(c)
318                }
319                let card = self.cnv_min_max(min, max)?;
320                Ok(Self::mk_card_group(Rbe::and(cs), card))
321            }
322            ast::TripleExpr::OneOf {
323                id: _,
324                expressions,
325                min,
326                max,
327                sem_acts: _,
328                annotations: _,
329            } => {
330                let mut cs = Vec::new();
331                for e in expressions {
332                    let c = self.triple_expr2rbe(&e.te, compiled_schema, current_table)?;
333                    cs.push(c)
334                }
335                let card = self.cnv_min_max(min, max)?;
336                Ok(Self::mk_card_group(Rbe::or(cs), card))
337            }
338            ast::TripleExpr::TripleConstraint {
339                id: _,
340                negated: _,
341                inverse: _,
342                predicate,
343                value_expr,
344                min,
345                max,
346                sem_acts: _,
347                annotations: _,
348            } => {
349                let min = self.cnv_min(min)?;
350                let max = self.cnv_max(max)?;
351                let iri = Self::cnv_predicate(predicate)?;
352                let cond = self.value_expr2match_cond(value_expr, compiled_schema)?;
353                let c = current_table.add_component(iri, &cond);
354                Ok(Rbe::symbol(c, min.value, max))
355            }
356            ast::TripleExpr::TripleExprRef(r) => Err(SchemaIRError::Todo {
357                msg: format!("TripleExprRef {r:?}"),
358            }),
359        }
360    }
361
362    fn cnv_predicate(predicate: &IriRef) -> CResult<Pred> {
363        match predicate {
364            IriRef::Iri(iri) => Ok(Pred::from(iri.clone())),
365            IriRef::Prefixed { prefix, local } => Err(SchemaIRError::Internal {
366                msg: format!(
367                    "Cannot convert prefixed {prefix}:{local} to predicate without context"
368                ),
369            }),
370        }
371    }
372
373    fn cnv_min_max(&self, min: &Option<i32>, max: &Option<i32>) -> CResult<Cardinality> {
374        let min = self.cnv_min(min)?;
375        let max = self.cnv_max(max)?;
376        Ok(Cardinality::from(min, max))
377    }
378
379    fn mk_card_group(rbe: Rbe<Component>, card: Cardinality) -> Rbe<Component> {
380        match &card {
381            c if c.is_1_1() => rbe,
382            c if c.is_star() => Rbe::Star {
383                value: Box::new(rbe),
384            },
385            c if c.is_plus() => Rbe::Plus {
386                value: Box::new(rbe),
387            },
388            _c => Rbe::Repeat {
389                value: Box::new(rbe),
390                card,
391            },
392        }
393    }
394
395    fn cnv_min(&self, min: &Option<i32>) -> CResult<Min> {
396        match min {
397            Some(min) if *min < 0 => Err(SchemaIRError::MinLessZero { min: *min }),
398            Some(min) => Ok(Min::from(*min)),
399            None => Ok(Min::from(1)),
400        }
401    }
402
403    fn cnv_max(&self, max: &Option<i32>) -> CResult<Max> {
404        match *max {
405            Some(-1) => Ok(Max::Unbounded),
406            Some(max) if max < -1 => Err(SchemaIRError::MaxIncorrect { max }),
407            Some(max) => Ok(Max::from(max)),
408            None => Ok(Max::from(1)),
409        }
410    }
411
412    fn value_expr2match_cond(
413        &self,
414        ve: &Option<Box<ast::ShapeExpr>>,
415        compiled_schema: &mut SchemaIR,
416    ) -> CResult<Cond> {
417        if let Some(se) = ve.as_deref() {
418            match se {
419                ast::ShapeExpr::NodeConstraint(nc) => self.cnv_node_constraint(
420                    &nc.node_kind(),
421                    &nc.datatype(),
422                    &nc.xs_facet(),
423                    &nc.values(),
424                ),
425
426                ast::ShapeExpr::Ref(sref) => {
427                    let idx = self.ref2idx(sref, compiled_schema)?;
428                    Ok(mk_cond_ref(idx))
429                }
430                ast::ShapeExpr::Shape { .. } => todo("value_expr2match_cond: Shape"),
431                ast::ShapeExpr::ShapeAnd { .. } => todo("value_expr2match_cond: ShapeOr"),
432                ast::ShapeExpr::ShapeOr { .. } => todo("value_expr2match_cond: ShapeOr"),
433                ast::ShapeExpr::ShapeNot { shape_expr } => {
434                    let new_idx = compiled_schema.new_index();
435                    let se = self.compile_shape_expr(&shape_expr.se, &new_idx, compiled_schema)?;
436                    let display = match compiled_schema.find_shape_idx(&new_idx) {
437                        None => "internal NOT".to_string(),
438                        Some((Some(label), _)) => compiled_schema.show_label(label),
439                        Some((None, _)) => "internal NOT with some shape expr".to_string(),
440                    };
441                    let not_se = ShapeExpr::ShapeNot {
442                        expr: Box::new(se),
443                        display,
444                    };
445                    compiled_schema.replace_shape(&new_idx, not_se);
446                    Ok(mk_cond_ref(new_idx))
447                }
448                ast::ShapeExpr::External => todo("value_expr2match_cond: ShapeExternal"),
449            }
450        } else {
451            Ok(MatchCond::single(SingleCond::new().with_name(".")))
452        }
453    }
454
455    /* #[allow(dead_code)]
456    fn shape_expr2match_cond(
457        &self,
458        _se: schema_json::ShapeExpr,
459        _compiled_schema: &mut SchemaIR,
460    ) -> CResult<Cond> {
461        todo("shape_expr2match_cond")
462    }*/
463
464    fn get_preds_shape(shape: &ast::Shape) -> Vec<Pred> {
465        match shape.triple_expr() {
466            None => Vec::new(),
467            Some(te) => Self::get_preds_triple_expr(&te),
468        }
469    }
470
471    fn get_preds_triple_expr(te: &ast::TripleExpr) -> Vec<Pred> {
472        match te {
473            ast::TripleExpr::EachOf { expressions, .. } => expressions
474                .iter()
475                .flat_map(|te| Self::get_preds_triple_expr(&te.te))
476                .collect(),
477            ast::TripleExpr::OneOf { expressions, .. } => expressions
478                .iter()
479                .flat_map(|te| Self::get_preds_triple_expr(&te.te))
480                .collect(),
481            ast::TripleExpr::TripleConstraint { predicate, .. } => {
482                let pred = iri_ref2iri_s(predicate);
483                vec![Pred::new(pred)]
484            }
485            ast::TripleExpr::TripleExprRef(_) => todo!(),
486        }
487    }
488
489    fn get_references_shape(
490        &self,
491        shape: &ast::Shape,
492        schema: &SchemaIR,
493    ) -> HashMap<Pred, Vec<ShapeLabelIdx>> {
494        match shape.triple_expr() {
495            None => HashMap::new(),
496            Some(te) => self.get_references_triple_expr(&te, schema),
497        }
498    }
499
500    fn get_references_triple_expr(
501        &self,
502        te: &ast::TripleExpr,
503        schema: &SchemaIR,
504    ) -> HashMap<Pred, Vec<ShapeLabelIdx>> {
505        match te {
506            ast::TripleExpr::EachOf { expressions, .. } => {
507                expressions.iter().fold(HashMap::new(), |mut acc, te| {
508                    let refs = self.get_references_triple_expr(&te.te, schema);
509                    for (pred, idxs) in refs {
510                        acc.entry(pred).or_default().extend(idxs);
511                    }
512                    acc
513                })
514            }
515            ast::TripleExpr::OneOf { expressions, .. } => {
516                expressions.iter().fold(HashMap::new(), |mut acc, te| {
517                    let refs = self.get_references_triple_expr(&te.te, schema);
518                    for (pred, idxs) in refs {
519                        acc.entry(pred).or_default().extend(idxs);
520                    }
521                    acc
522                })
523            }
524            ast::TripleExpr::TripleConstraint {
525                predicate,
526                value_expr,
527                ..
528            } => {
529                let pred = iri_ref2iri_s(predicate);
530                match value_expr {
531                    Some(ve) => match ve.as_ref() {
532                        ast::ShapeExpr::Ref(sref) => {
533                            let label =
534                                self.shape_expr_label_to_shape_label(sref)
535                                    .unwrap_or_else(|_| {
536                                        panic!("Convert shape label to IR label {sref}")
537                                    });
538                            let idx = schema.get_shape_label_idx(&label).unwrap_or_else(|_| {
539                                panic!("Failed to get shape label index for {label}")
540                            });
541                            let mut map = HashMap::new();
542                            map.insert(Pred::new(pred), vec![idx]);
543                            map
544                        }
545                        _ => HashMap::new(),
546                    },
547                    None => HashMap::new(),
548                }
549            }
550            ast::TripleExpr::TripleExprRef(_) => todo!(),
551        }
552    }
553}
554
555fn iri_ref2iri_s(iri_ref: &IriRef) -> IriS {
556    match iri_ref {
557        IriRef::Iri(iri) => iri.clone(),
558        IriRef::Prefixed { prefix, local } => {
559            panic!("Compiling schema...found prefixed iri: {prefix}:{local}")
560        }
561    }
562}
563
564fn node_constraint2match_cond(
565    node_kind: &Option<ast::NodeKind>,
566    datatype: &Option<IriRef>,
567    xs_facet: &Option<Vec<ast::XsFacet>>,
568    values: &Option<ValueSet>,
569) -> CResult<Cond> {
570    let c1: Option<Cond> = node_kind.as_ref().map(node_kind2match_cond);
571    let c2 = datatype.as_ref().map(datatype2match_cond).transpose()?;
572    let c3 = xs_facet.as_ref().map(xs_facets2match_cond);
573    let c4 = values.as_ref().map(|vs| valueset2match_cond(vs.clone()));
574    let os = vec![c1, c2, c3, c4];
575    Ok(options2match_cond(os))
576}
577
578fn node_kind2match_cond(nodekind: &ast::NodeKind) -> Cond {
579    mk_cond_nodekind(nodekind.clone())
580}
581
582fn datatype2match_cond(datatype: &IriRef) -> CResult<Cond> {
583    //let iri = cnv_iri_ref(datatype)?;
584    Ok(mk_cond_datatype(datatype))
585}
586
587fn xs_facets2match_cond(xs_facets: &Vec<ast::XsFacet>) -> Cond {
588    let mut conds = Vec::new();
589    for xs_facet in xs_facets {
590        conds.push(xs_facet2match_cond(xs_facet))
591    }
592    MatchCond::And(conds)
593}
594
595fn xs_facet2match_cond(xs_facet: &ast::XsFacet) -> Cond {
596    match xs_facet {
597        ast::XsFacet::StringFacet(sf) => string_facet_to_match_cond(sf),
598        ast::XsFacet::NumericFacet(nf) => numeric_facet_to_match_cond(nf),
599    }
600}
601
602fn string_facet_to_match_cond(sf: &ast::StringFacet) -> Cond {
603    match sf {
604        ast::StringFacet::Length(len) => mk_cond_length(*len),
605        ast::StringFacet::MinLength(len) => mk_cond_min_length(*len),
606        ast::StringFacet::MaxLength(len) => mk_cond_max_length(*len),
607        ast::StringFacet::Pattern(_) => todo!(),
608    }
609}
610
611fn numeric_facet_to_match_cond(nf: &ast::NumericFacet) -> Cond {
612    match nf {
613        ast::NumericFacet::MinInclusive(_min) => todo!(),
614        ast::NumericFacet::MinExclusive(_) => todo!(),
615        ast::NumericFacet::MaxInclusive(_) => todo!(),
616        ast::NumericFacet::MaxExclusive(_) => todo!(),
617        ast::NumericFacet::TotalDigits(_) => todo!(),
618        ast::NumericFacet::FractionDigits(_) => todo!(),
619    }
620}
621
622fn valueset2match_cond(vs: ValueSet) -> Cond {
623    mk_cond_value_set(vs)
624}
625
626fn options2match_cond<T: IntoIterator<Item = Option<Cond>>>(os: T) -> Cond {
627    let vec: Vec<Cond> = os.into_iter().flatten().collect();
628    match &vec[..] {
629        [] => MatchCond::empty(),
630        [c] => c.clone(),
631        _ => MatchCond::And(vec),
632    }
633}
634
635fn mk_cond_ref(idx: ShapeLabelIdx) -> Cond {
636    MatchCond::ref_(idx)
637}
638
639fn mk_cond_datatype(datatype: &IriRef) -> Cond {
640    let dt = datatype.clone();
641    MatchCond::single(
642        SingleCond::new()
643            .with_name(format!("datatype({dt})").as_str())
644            .with_cond(move |value: &Node| match check_node_datatype(value, &dt) {
645                Ok(_) => Ok(Pending::new()),
646                Err(err) => Err(RbeError::MsgError {
647                    msg: format!("Datatype error: {err}"),
648                }),
649            }),
650    )
651}
652
653fn mk_cond_length(len: usize) -> Cond {
654    MatchCond::single(
655        SingleCond::new()
656            .with_name(format!("length({len})").as_str())
657            .with_cond(move |value: &Node| match check_node_length(value, len) {
658                Ok(_) => Ok(Pending::new()),
659                Err(err) => Err(RbeError::MsgError {
660                    msg: format!("Length error: {err}"),
661                }),
662            }),
663    )
664}
665
666fn mk_cond_min_length(len: usize) -> Cond {
667    MatchCond::single(
668        SingleCond::new()
669            .with_name(format!("minLength({len})").as_str())
670            .with_cond(
671                move |value: &Node| match check_node_min_length(value, len) {
672                    Ok(_) => Ok(Pending::new()),
673                    Err(err) => Err(RbeError::MsgError {
674                        msg: format!("MinLength error: {err}"),
675                    }),
676                },
677            ),
678    )
679}
680
681fn mk_cond_max_length(len: usize) -> Cond {
682    MatchCond::simple(format!("maxLength({len})").as_str(), move |value: &Node| {
683        match check_node_max_length(value, len) {
684            Ok(_) => Ok(Pending::new()),
685            Err(err) => Err(RbeError::MsgError {
686                msg: format!("MaxLength error: {err}"),
687            }),
688        }
689    })
690}
691
692fn mk_cond_nodekind(nodekind: ast::NodeKind) -> Cond {
693    MatchCond::single(
694        SingleCond::new()
695            .with_name(format!("nodekind({nodekind})").as_str())
696            .with_cond(
697                move |value: &Node| match check_node_node_kind(value, &nodekind) {
698                    Ok(_) => Ok(Pending::empty()),
699                    Err(err) => Err(RbeError::MsgError {
700                        msg: format!("NodeKind Error: {err}"),
701                    }),
702                },
703            ),
704    )
705}
706
707fn iri_ref_2_shape_label(id: &IriRef) -> CResult<ShapeLabel> {
708    match id {
709        IriRef::Iri(iri) => Ok(ShapeLabel::Iri(iri.clone())),
710        IriRef::Prefixed { prefix, local } => Err(SchemaIRError::IriRef2ShapeLabelError {
711            prefix: prefix.clone(),
712            local: local.clone(),
713        }),
714    }
715}
716
717fn mk_cond_value_set(value_set: ValueSet) -> Cond {
718    MatchCond::single(
719        SingleCond::new()
720            .with_name(format!("{}", value_set).as_str())
721            .with_cond(move |node: &Node| {
722                if value_set.check_value(node.as_object()) {
723                    Ok(Pending::empty())
724                } else {
725                    Err(RbeError::MsgError {
726                        msg: format!("Values failed: {node} not in {value_set}"),
727                    })
728                }
729            }),
730    )
731}
732
733fn create_value_set(values: &Vec<ast::ValueSetValue>) -> CResult<ValueSet> {
734    let mut vs = ValueSet::new();
735    for v in values {
736        let cvalue = cnv_value(v)?;
737        vs.add_value(cvalue)
738    }
739    Ok(vs)
740}
741
742fn cnv_value(v: &ast::ValueSetValue) -> CResult<ValueSetValue> {
743    match &v {
744        ast::ValueSetValue::IriStem { stem, .. } => {
745            let cnv_stem = cnv_iri_ref(stem)?;
746            Ok(ValueSetValue::IriStem { stem: cnv_stem })
747        }
748        ast::ValueSetValue::ObjectValue(ovw) => {
749            let ov = cnv_object_value(ovw)?;
750            Ok(ValueSetValue::ObjectValue(ov))
751        }
752        ast::ValueSetValue::Language { language_tag, .. } => Ok(ValueSetValue::Language {
753            language_tag: language_tag.to_string(),
754        }),
755        ast::ValueSetValue::LiteralStem { stem, .. } => Ok(ValueSetValue::LiteralStem {
756            stem: stem.to_string(),
757        }),
758        ast::ValueSetValue::LiteralStemRange { .. } => {
759            todo!()
760            /*let stem = cnv_string_or_wildcard(&stem)?;
761            let exclusions = cnv_opt_vec(&exclusions, cnv_string_or_literalstem)?;
762            Ok(ValueSetValue::LiteralStemRange { stem, exclusions })*/
763        }
764        _ => todo!(),
765    }
766}
767
768/*
769fn cnv_node_kind(_nk: &ast::NodeKind) -> CResult<NodeKind> {
770    todo!()
771}
772
773fn cnv_xs_facet(_xsf: &ast::XsFacet) -> CResult<XsFacet> {
774    todo!()
775}
776
777fn cnv_vec<A, B, F>(vs: Vec<A>, func: F) -> CResult<Vec<B>>
778where
779    F: Fn(&A) -> CResult<B>,
780{
781    let mut rs = Vec::new();
782    for v in vs {
783        let b = func(&v)?;
784        rs.push(b);
785    }
786    Ok(rs)
787}
788
789fn cnv_opt_vec<A, B, F>(maybe_vs: &Option<Vec<A>>, func: F) -> CResult<Option<Vec<B>>>
790where
791    F: Fn(&A) -> CResult<B>,
792{
793    match maybe_vs {
794        None => Ok(None),
795        Some(vs) => {
796            let mut rs = Vec::new();
797            for v in vs {
798                match func(v) {
799                    Err(err) => return Err(err),
800                    Ok(result) => {
801                        rs.push(result);
802                    }
803                }
804            }
805            Ok(Some(rs))
806        }
807    }
808}
809
810fn cnv_opt<A, B, F>(maybe_vs: &Option<A>, func: F) -> CResult<Option<B>>
811where
812    F: Fn(&A) -> CResult<B>,
813{
814    match maybe_vs {
815        None => Ok(None),
816        Some(vs) => match func(vs) {
817            Err(err) => Err(err),
818            Ok(v) => Ok(Some(v)),
819        },
820    }
821}
822
823fn cnv_string_or_wildcard(_sw: &ast::StringOrWildcard) -> CResult<StringOrWildcard> {
824    todo!()
825}
826
827fn cnv_string_or_literalstem(
828    _sl: &ast::StringOrLiteralStemWrapper,
829) -> CResult<StringOrLiteralStem> {
830    todo!()
831}
832*/
833
834fn cnv_object_value(ov: &ast::ObjectValue) -> CResult<ObjectValue> {
835    match ov {
836        ast::ObjectValue::IriRef(ir) => {
837            let iri = cnv_iri_ref(ir)?;
838            Ok(ObjectValue::IriRef(iri))
839        }
840        ast::ObjectValue::Literal(lit) => Ok(ObjectValue::ObjectLiteral(lit.clone())),
841    }
842}
843
844/*fn cnv_lang(lang: &String) -> CResult<Lang> {
845    Ok(Lang::new(lang.as_str()))
846}*/
847
848/*fn check_node_maybe_node_kind(node: &Node, nodekind: &Option<ast::NodeKind>) -> CResult<()> {
849    match nodekind {
850        None => Ok(()),
851        Some(nk) => check_node_node_kind(node, &nk),
852    }
853}*/
854
855fn check_node_node_kind(node: &Node, nk: &ast::NodeKind) -> CResult<()> {
856    match (nk, node.as_object()) {
857        (ast::NodeKind::Iri, Object::Iri { .. }) => Ok(()),
858        (ast::NodeKind::Iri, _) => Err(SchemaIRError::NodeKindIri { node: node.clone() }),
859        (ast::NodeKind::BNode, Object::BlankNode(_)) => Ok(()),
860        (ast::NodeKind::BNode, _) => Err(SchemaIRError::NodeKindBNode { node: node.clone() }),
861        (ast::NodeKind::Literal, Object::Literal(_)) => Ok(()),
862        (ast::NodeKind::Literal, _) => Err(SchemaIRError::NodeKindLiteral { node: node.clone() }),
863        (ast::NodeKind::NonLiteral, Object::BlankNode(_)) => Ok(()),
864        (ast::NodeKind::NonLiteral, Object::Iri { .. }) => Ok(()),
865        (ast::NodeKind::NonLiteral, _) => {
866            Err(SchemaIRError::NodeKindNonLiteral { node: node.clone() })
867        }
868    }
869}
870
871/*
872fn check_node_maybe_datatype(node: &Node, datatype: &Option<IriRef>) -> CResult<()> {
873    match datatype {
874        None => Ok(()),
875        Some(dt) => check_node_datatype(node, dt),
876    }
877}
878*/
879
880fn check_node_datatype(node: &Node, dt: &IriRef) -> CResult<()> {
881    debug!("check_node_datatype: {node:?} datatype: {dt}");
882    match node.as_object() {
883        Object::Literal(Literal::DatatypeLiteral {
884            ref datatype,
885            lexical_form,
886        }) => {
887            if dt == datatype {
888                Ok(())
889            } else {
890                Err(SchemaIRError::DatatypeDontMatch {
891                    expected: dt.clone(),
892                    found: datatype.clone(),
893                    lexical_form: lexical_form.clone(),
894                })
895            }
896        }
897        Object::Literal(Literal::StringLiteral {
898            lexical_form,
899            lang: None,
900        }) => {
901            debug!("StringLiteral...{}", *dt);
902            if *dt == *XSD_STRING {
903                debug!("datatype cond passes");
904                Ok(())
905            } else {
906                debug!("datatype cond fails: {}!={}", dt, *XSD_STRING);
907                Err(SchemaIRError::DatatypeDontMatchString {
908                    expected: dt.clone(),
909                    lexical_form: lexical_form.clone(),
910                })
911            }
912        }
913        Object::Literal(Literal::StringLiteral {
914            lexical_form,
915            lang: Some(lang),
916        }) => {
917            if *dt == *RDF_LANG_STRING {
918                Ok(())
919            } else {
920                Err(SchemaIRError::DatatypeDontMatchLangString {
921                    lexical_form: lexical_form.clone(),
922                    lang: Box::new(lang.clone()),
923                })
924            }
925        }
926        _ => Err(SchemaIRError::DatatypeNoLiteral {
927            expected: Box::new(dt.clone()),
928            node: Box::new(node.clone()),
929        }),
930    }
931}
932
933fn check_node_length(node: &Node, len: usize) -> CResult<()> {
934    debug!("check_node_length: {node:?} length: {len}");
935    let node_length = node.length();
936    if node_length == len {
937        Ok(())
938    } else {
939        Err(SchemaIRError::LengthError {
940            expected: len,
941            found: node_length,
942            node: format!("{node}"),
943        })
944    }
945}
946
947fn check_node_min_length(node: &Node, len: usize) -> CResult<()> {
948    debug!("check_node_min_length: {node:?} min_length: {len}");
949    let node_length = node.length();
950    if node_length >= len {
951        Ok(())
952    } else {
953        Err(SchemaIRError::MinLengthError {
954            expected: len,
955            found: node_length,
956            node: format!("{node}"),
957        })
958    }
959}
960
961fn check_node_max_length(node: &Node, len: usize) -> CResult<()> {
962    debug!("check_node_max_length: {node:?} max_length: {len}");
963    let node_length = node.length();
964    if node_length <= len {
965        Ok(())
966    } else {
967        Err(SchemaIRError::MaxLengthError {
968            expected: len,
969            found: node_length,
970            node: format!("{node}"),
971        })
972    }
973}
974
975/*
976fn check_node_min_inclusive(node: &Node, min: &NumericLiteral) -> CResult<()> {
977    debug!("check_node_min_inclusive: {node:?} min: {min}");
978    if let Some(node_number) = node.numeric_value() {
979        if node_number.less_than(min) {
980            Ok(())
981        } else {
982            Err(SchemaIRError::MinInclusiveError {
983                expected: min.clone(),
984                found: node_number,
985                node: format!("{node}"),
986            })
987        }
988    } else {
989        Err(SchemaIRError::NonNumeric {
990            node: format!("{node}"),
991        })
992    }
993}
994*/
995
996/*fn check_node_xs_facets(node: &Object, xs_facets: &Vec<XsFacet>) -> CResult<()> {
997    Ok(()) // todo!()
998}*/
999
1000fn todo<A>(str: &str) -> CResult<A> {
1001    Err(SchemaIRError::Todo {
1002        msg: str.to_string(),
1003    })
1004}
1005
1006fn cnv_iri_ref(iri: &IriRef) -> Result<IriS, SchemaIRError> {
1007    match iri {
1008        IriRef::Iri(iri) => Ok(iri.clone()),
1009        _ => Err(SchemaIRError::Internal {
1010            msg: format!("Cannot convert {iri} to Iri"),
1011        }),
1012    }
1013}