1use iref::{Iri, IriBuf, IriRef, IriRefBuf};
2use langtag::LanguageTagBuf;
3use locspan::Meta;
4use rdf_types::{
5 literal::Type, BlankIdVocabulary, BlankIdVocabularyMut, Generator, IriVocabulary,
6 IriVocabularyMut, LanguageTagVocabulary, LanguageTagVocabularyMut, Namespace, Triple,
7};
8use static_iref::iri;
9use std::collections::HashMap;
10
11const RDF_TYPE: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
12const RDF_LIST: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#List");
13const RDF_NIL: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
14const RDF_FIRST: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
15const RDF_REST: Iri<'static> = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
16const XSD_BOOLEAN: Iri<'static> = iri!("http://www.w3.org/2001/XMLSchema#boolean");
17const XSD_INTEGER: Iri<'static> = iri!("http://www.w3.org/2001/XMLSchema#integer");
18const XSD_DECIMAL: Iri<'static> = iri!("http://www.w3.org/2001/XMLSchema#decimal");
19const XSD_DOUBLE: Iri<'static> = iri!("http://www.w3.org/2001/XMLSchema#double");
20
21pub type MetaTriple<M, V = ()> = Meta<
23 Triple<
24 Meta<rdf_types::Subject<<V as IriVocabulary>::Iri, <V as BlankIdVocabulary>::BlankId>, M>,
25 Meta<<V as IriVocabulary>::Iri, M>,
26 Meta<
27 rdf_types::meta::Object<
28 M,
29 rdf_types::Id<<V as IriVocabulary>::Iri, <V as BlankIdVocabulary>::BlankId>,
30 rdf_types::literal::Type<
31 <V as IriVocabulary>::Iri,
32 <V as LanguageTagVocabulary>::LanguageTag,
33 >,
34 >,
35 M,
36 >,
37 >,
38 M,
39>;
40
41#[derive(Debug, thiserror::Error)]
42pub enum Error {
43 #[error("cannot resolve relative IRI <{0}>: no base IRI")]
44 NoBaseIri(IriRefBuf),
45
46 #[error("unknown IRI prefix `{0}`")]
47 UnknownPrefix(String),
48
49 #[error("invalid compact IRI suffix in `{prefix}:{invalid_suffix}`")]
50 InvalidCompactIriSuffix {
51 prefix: String,
52 iri: IriBuf,
53 invalid_suffix: String,
54 },
55}
56
57pub type MetaError<M> = Meta<Box<Error>, M>;
58
59impl<M: Clone> crate::Document<M> {
60 pub fn build_triples(
61 &self,
62 base_iri: Option<IriBuf>,
63 mut generator: impl Generator<()>,
64 ) -> Result<Vec<MetaTriple<M, ()>>, MetaError<M>> {
65 let mut triples = Vec::new();
66 let mut context = Context::new(
67 base_iri,
68 rdf_types::vocabulary::no_vocabulary_mut(),
69 &mut generator,
70 );
71 self.build(&mut context, &mut triples)?;
72 Ok(triples)
73 }
74
75 pub fn build_triples_with<
76 V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
77 >(
78 &self,
79 base_iri: Option<V::Iri>,
80 vocabulary: &mut V,
81 mut generator: impl Generator<V>,
82 ) -> Result<Vec<MetaTriple<M, V>>, MetaError<M>>
83 where
84 V::Iri: Clone,
85 V::BlankId: Clone,
86 {
87 let mut triples = Vec::new();
88 let mut context = Context::new(base_iri, vocabulary, &mut generator);
89 self.build(&mut context, &mut triples)?;
90 Ok(triples)
91 }
92}
93
94pub struct Context<'v, 'g, M, V: IriVocabulary, G> {
95 vocabulary: &'v mut V,
96 generator: &'g mut G,
97 base_iri: Option<V::Iri>,
98 prefixes: HashMap<String, Meta<V::Iri, M>>,
99}
100
101impl<'v, 'g, M, V: IriVocabulary, G> Context<'v, 'g, M, V, G> {
102 pub fn new(base_iri: Option<V::Iri>, vocabulary: &'v mut V, generator: &'g mut G) -> Self {
103 Self {
104 vocabulary,
105 generator,
106 base_iri,
107 prefixes: HashMap::new(),
108 }
109 }
110
111 pub fn resolve_iri_ref(
112 &mut self,
113 Meta(iri_ref, meta): Meta<IriRef, &M>,
114 ) -> Result<V::Iri, MetaError<M>>
115 where
116 M: Clone,
117 V: IriVocabularyMut,
118 {
119 match &self.base_iri {
120 Some(current) => {
121 let iri = iri_ref.resolved(self.vocabulary.iri(current).unwrap());
122 Ok(self.vocabulary.insert(iri.as_iri()))
123 }
124 None => match iri_ref.into_iri() {
125 Ok(iri) => Ok(self.vocabulary.insert(iri)),
126 Err(_) => Err(Meta(
127 Box::new(Error::NoBaseIri(iri_ref.to_owned())),
128 meta.clone(),
129 )),
130 },
131 }
132 }
133
134 pub fn resolve_compact_iri(
135 &mut self,
136 prefix: Meta<&str, &M>,
137 suffix: Meta<&str, &M>,
138 meta: &M,
139 ) -> Result<V::Iri, MetaError<M>>
140 where
141 M: Clone,
142 V: IriVocabularyMut,
143 {
144 match self.prefixes.get(prefix.0) {
145 Some(iri) => {
146 let iri = self.vocabulary.iri(iri).unwrap();
147 let mut buffer = iri.to_string();
148 buffer.push_str(suffix.0);
149 match Iri::new(&buffer) {
150 Ok(result) => Ok(self.vocabulary.insert(result)),
151 Err(_) => Err(Meta(
152 Box::new(Error::InvalidCompactIriSuffix {
153 prefix: prefix.0.to_owned(),
154 iri: iri.to_owned(),
155 invalid_suffix: suffix.0.to_owned(),
156 }),
157 meta.clone(),
158 )),
159 }
160 }
161 None => Err(Meta(
162 Box::new(Error::UnknownPrefix(prefix.0.to_owned())),
163 prefix.1.clone(),
164 )),
165 }
166 }
167
168 pub fn insert_prefix(&mut self, prefix: String, iri: V::Iri, meta: M) {
169 self.prefixes.insert(prefix, Meta(iri, meta));
170 }
171}
172
173pub trait RdfVocabulary:
174 IriVocabulary
175 + BlankIdVocabulary
176 + LanguageTagVocabulary
177 + Namespace<Id = rdf_types::Id<Self::Iri, Self::BlankId>>
178{
179}
180
181impl<
182 V: IriVocabulary
183 + BlankIdVocabulary
184 + LanguageTagVocabulary
185 + Namespace<Id = rdf_types::Id<V::Iri, V::BlankId>>,
186 > RdfVocabulary for V
187{
188}
189
190pub trait Build<M, V: RdfVocabulary, G> {
191 fn build(
192 &self,
193 context: &mut Context<M, V, G>,
194 triples: &mut Vec<MetaTriple<M, V>>,
195 ) -> Result<(), MetaError<M>>;
196}
197
198impl<
199 M: Clone,
200 V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
201 G: Generator<V>,
202 > Build<M, V, G> for crate::Document<M>
203where
204 V::Iri: Clone,
205 V::BlankId: Clone,
206{
207 fn build(
208 &self,
209 context: &mut Context<M, V, G>,
210 triples: &mut Vec<MetaTriple<M, V>>,
211 ) -> Result<(), MetaError<M>> {
212 for statement in &self.statements {
213 match statement {
214 Meta(crate::Statement::Directive(directive), meta) => match directive {
215 crate::Directive::Base(iri) | crate::Directive::SparqlBase(iri) => {
216 let iri_ref = iri.borrow().map(IriRefBuf::as_iri_ref);
217 context.base_iri = Some(context.resolve_iri_ref(iri_ref)?);
218 }
219 crate::Directive::Prefix(prefix, iri)
220 | crate::Directive::SparqlPrefix(prefix, iri) => {
221 let iri_ref = iri.borrow().map(IriRefBuf::as_iri_ref);
222 let iri = context.resolve_iri_ref(iri_ref)?;
223 context.insert_prefix(prefix.value().clone(), iri, meta.clone());
224 }
225 },
226 Meta(crate::Statement::Triples(t), meta) => {
227 t.build(context, meta, triples)?;
228 }
229 }
230 }
231
232 Ok(())
233 }
234}
235
236impl<M: Clone> crate::Triples<M> {
237 fn build<
238 V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
239 G: Generator<V>,
240 >(
241 &self,
242 context: &mut Context<M, V, G>,
243 meta: &M,
244 triples: &mut Vec<MetaTriple<M, V>>,
245 ) -> Result<(), MetaError<M>>
246 where
247 V::Iri: Clone,
248 V::BlankId: Clone,
249 {
250 let subject = self.subject.build(context, triples)?;
251
252 for Meta(po_list, _) in self.predicate_objects_list.iter() {
253 po_list.build(context, meta, &subject, triples)?;
254 }
255
256 Ok(())
257 }
258}
259
260impl<M: Clone> crate::PredicateObjects<M> {
261 fn build<
262 V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
263 G: Generator<V>,
264 >(
265 &self,
266 context: &mut Context<M, V, G>,
267 meta: &M,
268 subject: &Meta<rdf_types::Subject<V::Iri, V::BlankId>, M>,
269 triples: &mut Vec<MetaTriple<M, V>>,
270 ) -> Result<(), MetaError<M>>
271 where
272 V::Iri: Clone,
273 V::BlankId: Clone,
274 {
275 let predicate = self.verb.build(context, triples)?;
276
277 for o in &self.objects.value().0 {
278 let object = o.build(context, triples)?;
279 triples.push(Meta(
280 rdf_types::Triple(subject.clone(), predicate.clone(), object),
281 meta.clone(),
282 ))
283 }
284
285 Ok(())
286 }
287}
288
289trait BuildFragment<M, V: RdfVocabulary + BlankIdVocabulary, G> {
290 type Target;
291
292 fn build(
293 &self,
294 context: &mut Context<M, V, G>,
295 triples: &mut Vec<MetaTriple<M, V>>,
296 ) -> Result<Self::Target, MetaError<M>>;
297}
298
299impl<T: BuildMetaFragment<M, V, G>, M: Clone, V: RdfVocabulary + BlankIdVocabulary, G>
300 BuildFragment<M, V, G> for Meta<T, M>
301{
302 type Target = Meta<T::Target, M>;
303
304 fn build(
305 &self,
306 context: &mut Context<M, V, G>,
307 triples: &mut Vec<MetaTriple<M, V>>,
308 ) -> Result<Self::Target, MetaError<M>> {
309 Ok(Meta(
310 self.value().build(context, self.metadata(), triples)?,
311 self.metadata().clone(),
312 ))
313 }
314}
315
316trait BuildMetaFragment<M, V: RdfVocabulary, G> {
317 type Target;
318
319 fn build(
320 &self,
321 context: &mut Context<M, V, G>,
322 meta: &M,
323 triples: &mut Vec<MetaTriple<M, V>>,
324 ) -> Result<Self::Target, MetaError<M>>;
325}
326
327impl<M: Clone, V: RdfVocabulary + IriVocabularyMut + BlankIdVocabulary, G>
328 BuildMetaFragment<M, V, G> for crate::Iri<M>
329{
330 type Target = V::Iri;
331
332 fn build(
333 &self,
334 context: &mut Context<M, V, G>,
335 meta: &M,
336 _triples: &mut Vec<MetaTriple<M, V>>,
337 ) -> Result<Self::Target, MetaError<M>> {
338 match self {
339 Self::IriRef(iri_ref) => context.resolve_iri_ref(Meta(iri_ref.as_iri_ref(), meta)),
340 Self::Compact(prefix, suffix) => context.resolve_compact_iri(
341 prefix.borrow().map(String::as_str),
342 suffix.borrow().map(String::as_str),
343 meta,
344 ),
345 }
346 }
347}
348
349impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::BlankNode<M>
350where
351 V: IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
352 V::Iri: Clone,
353 V::BlankId: Clone,
354{
355 type Target = rdf_types::Subject<V::Iri, V::BlankId>;
356
357 fn build(
358 &self,
359 context: &mut Context<M, V, G>,
360 meta: &M,
361 triples: &mut Vec<MetaTriple<M, V>>,
362 ) -> Result<Self::Target, MetaError<M>> {
363 match self {
364 Self::Label(b) => Ok(rdf_types::Subject::Blank(
365 context.vocabulary.insert_blank_id(b),
366 )),
367 Self::Anonymous(b_property_list) => {
368 let b = Meta(context.generator.next(context.vocabulary), meta.clone());
369
370 for predicate_objects in b_property_list.iter() {
371 predicate_objects.build(context, meta, &b, triples)?;
372 }
373
374 Ok(b.0)
375 }
376 }
377 }
378}
379
380impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::Subject<M>
381where
382 V: IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
383 V::Iri: Clone,
384 V::BlankId: Clone,
385{
386 type Target = rdf_types::Subject<V::Iri, V::BlankId>;
387
388 fn build(
389 &self,
390 context: &mut Context<M, V, G>,
391 meta: &M,
392 triples: &mut Vec<MetaTriple<M, V>>,
393 ) -> Result<Self::Target, MetaError<M>> {
394 match self {
395 Self::Iri(iri) => Ok(rdf_types::Subject::Iri(iri.build(context, meta, triples)?)),
396 Self::BlankNode(b) => Ok(b.build(context, meta, triples)?),
397 Self::Collection(collection) => collection.build(context, meta, triples),
398 }
399 }
400}
401
402impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G>
403 for crate::Collection<M>
404where
405 V: IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
406 V::Iri: Clone,
407 V::BlankId: Clone,
408{
409 type Target = rdf_types::Subject<V::Iri, V::BlankId>;
410
411 fn build(
412 &self,
413 context: &mut Context<M, V, G>,
414 meta: &M,
415 triples: &mut Vec<MetaTriple<M, V>>,
416 ) -> Result<Self::Target, MetaError<M>> {
417 let mut head = rdf_types::Subject::Iri(context.vocabulary.insert(RDF_NIL));
418
419 for o in self.0.iter().rev() {
420 let item = o.build(context, triples)?;
421 let node = context.generator.next(context.vocabulary);
422
423 triples.push(Meta(
424 rdf_types::Triple(
425 Meta(node.clone(), item.metadata().clone()),
426 Meta(context.vocabulary.insert(RDF_TYPE), item.metadata().clone()),
427 Meta(
428 rdf_types::Term::Id(rdf_types::Id::Iri(
429 context.vocabulary.insert(RDF_LIST),
430 )),
431 item.metadata().clone(),
432 ),
433 ),
434 meta.clone(),
435 ));
436
437 triples.push(Meta(
438 rdf_types::Triple(
439 Meta(node.clone(), item.metadata().clone()),
440 Meta(context.vocabulary.insert(RDF_REST), item.metadata().clone()),
441 Meta(head.into_term(), item.metadata().clone()),
442 ),
443 meta.clone(),
444 ));
445
446 triples.push(Meta(
447 rdf_types::Triple(
448 Meta(node.clone(), item.metadata().clone()),
449 Meta(
450 context.vocabulary.insert(RDF_FIRST),
451 item.metadata().clone(),
452 ),
453 item,
454 ),
455 meta.clone(),
456 ));
457
458 head = node;
459 }
460
461 Ok(head)
462 }
463}
464
465impl<M: Clone, V: RdfVocabulary + IriVocabularyMut, G> BuildMetaFragment<M, V, G>
466 for crate::Verb<M>
467{
468 type Target = V::Iri;
469
470 fn build(
471 &self,
472 context: &mut Context<M, V, G>,
473 meta: &M,
474 triples: &mut Vec<MetaTriple<M, V>>,
475 ) -> Result<Self::Target, MetaError<M>> {
476 match self {
477 Self::A => Ok(context.vocabulary.insert(RDF_TYPE)),
478 Self::Predicate(i) => i.build(context, meta, triples),
479 }
480 }
481}
482
483impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::Object<M>
484where
485 V: IriVocabularyMut + BlankIdVocabularyMut + LanguageTagVocabularyMut,
486 V::Iri: Clone,
487 V::BlankId: Clone,
488{
489 type Target =
490 rdf_types::meta::Object<M, rdf_types::Id<V::Iri, V::BlankId>, Type<V::Iri, V::LanguageTag>>;
491
492 fn build(
493 &self,
494 context: &mut Context<M, V, G>,
495 meta: &M,
496 triples: &mut Vec<MetaTriple<M, V>>,
497 ) -> Result<Self::Target, MetaError<M>> {
498 match self {
499 Self::Iri(iri) => Ok(rdf_types::Object::Id(rdf_types::Id::Iri(
500 iri.build(context, meta, triples)?,
501 ))),
502 Self::BlankNode(b) => Ok(b.build(context, meta, triples)?.into_term()),
503 Self::Collection(collection) => {
504 Ok(collection.build(context, meta, triples)?.into_term())
505 }
506 Self::Literal(literal) => Ok(rdf_types::Object::Literal(
507 literal.build(context, meta, triples)?,
508 )),
509 }
510 }
511}
512
513impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::Literal<M>
514where
515 V: IriVocabularyMut + BlankIdVocabulary + LanguageTagVocabularyMut,
516{
517 type Target = rdf_types::meta::Literal<M, Type<V::Iri, V::LanguageTag>>;
518
519 fn build(
520 &self,
521 context: &mut Context<M, V, G>,
522 meta: &M,
523 triples: &mut Vec<MetaTriple<M, V>>,
524 ) -> Result<Self::Target, MetaError<M>> {
525 match self {
526 Self::Boolean(b) => b.build(context, meta, triples),
527 Self::Numeric(n) => n.build(context, meta, triples),
528 Self::Rdf(literal) => literal.build(context, meta, triples),
529 }
530 }
531}
532
533impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for bool
534where
535 V: IriVocabularyMut + BlankIdVocabulary + LanguageTagVocabulary,
536{
537 type Target = rdf_types::meta::Literal<M, Type<V::Iri, V::LanguageTag>>;
538
539 fn build(
540 &self,
541 context: &mut Context<M, V, G>,
542 meta: &M,
543 _triples: &mut Vec<MetaTriple<M, V>>,
544 ) -> Result<Self::Target, MetaError<M>> {
545 let s = if *self { "true" } else { "false" };
546
547 Ok(rdf_types::meta::Literal::new(
548 Meta(s.to_owned(), meta.clone()),
549 Meta(
550 rdf_types::literal::Type::Any(context.vocabulary.insert(XSD_BOOLEAN)),
551 meta.clone(),
552 ),
553 ))
554 }
555}
556
557impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::NumericLiteral
558where
559 V: IriVocabularyMut + BlankIdVocabulary + LanguageTagVocabulary,
560{
561 type Target = rdf_types::meta::Literal<M, Type<V::Iri, V::LanguageTag>>;
562
563 fn build(
564 &self,
565 context: &mut Context<M, V, G>,
566 meta: &M,
567 _triples: &mut Vec<MetaTriple<M, V>>,
568 ) -> Result<Self::Target, MetaError<M>> {
569 let (s, ty) = match self {
570 Self::Integer(i) => (i.as_str(), XSD_INTEGER),
571 Self::Decimal(d) => (d.as_str(), XSD_DECIMAL),
572 Self::Double(d) => (d.as_str(), XSD_DOUBLE),
573 };
574
575 Ok(rdf_types::meta::Literal::new(
576 Meta(s.to_owned(), meta.clone()),
577 Meta(Type::Any(context.vocabulary.insert(ty)), meta.clone()),
578 ))
579 }
580}
581
582impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::RdfLiteral<M>
583where
584 V: IriVocabularyMut + BlankIdVocabulary + LanguageTagVocabularyMut,
585{
586 type Target = rdf_types::meta::Literal<M, Type<V::Iri, V::LanguageTag>>;
587
588 fn build(
589 &self,
590 context: &mut Context<M, V, G>,
591 _meta: &M,
592 triples: &mut Vec<MetaTriple<M, V>>,
593 ) -> Result<Self::Target, MetaError<M>> {
594 let type_ = match self.type_() {
595 Meta(rdf_types::literal::Type::Any(t), meta) => Meta(
596 rdf_types::literal::Type::Any(t.build(context, meta, triples)?),
597 meta.clone(),
598 ),
599 Meta(rdf_types::literal::Type::LangString(tag), meta) => Meta(
600 rdf_types::literal::Type::LangString(tag.build(context, meta, triples)?),
601 meta.clone(),
602 ),
603 };
604
605 Ok(rdf_types::meta::Literal::new(self.value().clone(), type_))
606 }
607}
608
609impl<M: Clone, V: RdfVocabulary + LanguageTagVocabularyMut, G> BuildMetaFragment<M, V, G>
610 for LanguageTagBuf
611{
612 type Target = V::LanguageTag;
613
614 fn build(
615 &self,
616 context: &mut Context<M, V, G>,
617 _meta: &M,
618 _triples: &mut Vec<MetaTriple<M, V>>,
619 ) -> Result<Self::Target, MetaError<M>> {
620 Ok(context.vocabulary.insert_language_tag(self.as_ref()))
621 }
622}