1use crate::model::RdfTerm;
4use crate::model::{BlankNode, Literal, NamedNode, Object, Predicate, Subject, Variable};
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::hash::Hash;
8
9#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
43pub struct Triple {
44 subject: Subject,
45 predicate: Predicate,
46 object: Object,
47}
48
49impl Triple {
50 pub fn new(
85 subject: impl Into<Subject>,
86 predicate: impl Into<Predicate>,
87 object: impl Into<Object>,
88 ) -> Self {
89 Triple {
90 subject: subject.into(),
91 predicate: predicate.into(),
92 object: object.into(),
93 }
94 }
95
96 pub fn as_ref(&self) -> TripleRef<'_> {
98 TripleRef::from(self)
99 }
100
101 pub fn subject(&self) -> &Subject {
103 &self.subject
104 }
105
106 pub fn predicate(&self) -> &Predicate {
108 &self.predicate
109 }
110
111 pub fn object(&self) -> &Object {
113 &self.object
114 }
115
116 pub fn into_parts(self) -> (Subject, Predicate, Object) {
118 (self.subject, self.predicate, self.object)
119 }
120
121 pub fn has_variables(&self) -> bool {
123 matches!(self.subject, Subject::Variable(_))
124 || matches!(self.predicate, Predicate::Variable(_))
125 || matches!(self.object, Object::Variable(_))
126 }
127
128 pub fn is_ground(&self) -> bool {
130 !self.has_variables()
131 }
132
133 pub fn matches_pattern(
137 &self,
138 subject: Option<&Subject>,
139 predicate: Option<&Predicate>,
140 object: Option<&Object>,
141 ) -> bool {
142 if let Some(s) = subject {
143 if &self.subject != s {
144 return false;
145 }
146 }
147
148 if let Some(p) = predicate {
149 if &self.predicate != p {
150 return false;
151 }
152 }
153
154 if let Some(o) = object {
155 if &self.object != o {
156 return false;
157 }
158 }
159
160 true
161 }
162
163 #[allow(dead_code)]
168 fn canonical_ordering(&self) -> (u8, &str, u8, &str, u8, &str) {
169 let subject_ord = match &self.subject {
170 Subject::NamedNode(_) => 0,
171 Subject::BlankNode(_) => 1,
172 Subject::Variable(_) => 2,
173 Subject::QuotedTriple(_) => 3,
174 };
175
176 let predicate_ord = match &self.predicate {
177 Predicate::NamedNode(_) => 0,
178 Predicate::Variable(_) => 1,
179 };
180
181 let object_ord = match &self.object {
182 Object::NamedNode(_) => 0,
183 Object::BlankNode(_) => 1,
184 Object::Literal(_) => 2,
185 Object::Variable(_) => 3,
186 Object::QuotedTriple(_) => 4,
187 };
188
189 (
190 subject_ord,
191 self.subject_str(),
192 predicate_ord,
193 self.predicate_str(),
194 object_ord,
195 self.object_str(),
196 )
197 }
198
199 #[allow(dead_code)]
201 fn subject_str(&self) -> &str {
202 match &self.subject {
203 Subject::NamedNode(n) => n.as_str(),
204 Subject::BlankNode(b) => b.as_str(),
205 Subject::Variable(v) => v.as_str(),
206 Subject::QuotedTriple(_) => "<<quoted-triple>>",
207 }
208 }
209
210 #[allow(dead_code)]
212 fn predicate_str(&self) -> &str {
213 match &self.predicate {
214 Predicate::NamedNode(n) => n.as_str(),
215 Predicate::Variable(v) => v.as_str(),
216 }
217 }
218
219 #[allow(dead_code)]
221 fn object_str(&self) -> &str {
222 match &self.object {
223 Object::NamedNode(n) => n.as_str(),
224 Object::BlankNode(b) => b.as_str(),
225 Object::Literal(l) => l.as_str(),
226 Object::Variable(v) => v.as_str(),
227 Object::QuotedTriple(_) => "<<quoted-triple>>",
228 }
229 }
230}
231
232impl fmt::Display for Triple {
233 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234 write!(f, "{} {} {} .", self.subject, self.predicate, self.object)
235 }
236}
237
238impl fmt::Display for Subject {
240 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
241 match self {
242 Subject::NamedNode(n) => write!(f, "{n}"),
243 Subject::BlankNode(b) => write!(f, "{b}"),
244 Subject::Variable(v) => write!(f, "{v}"),
245 Subject::QuotedTriple(qt) => write!(f, "{qt}"),
246 }
247 }
248}
249
250impl fmt::Display for Predicate {
251 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 match self {
253 Predicate::NamedNode(n) => write!(f, "{n}"),
254 Predicate::Variable(v) => write!(f, "{v}"),
255 }
256 }
257}
258
259impl fmt::Display for Object {
260 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261 match self {
262 Object::NamedNode(n) => write!(f, "{n}"),
263 Object::BlankNode(b) => write!(f, "{b}"),
264 Object::Literal(l) => write!(f, "{l}"),
265 Object::Variable(v) => write!(f, "{v}"),
266 Object::QuotedTriple(qt) => write!(f, "{qt}"),
267 }
268 }
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
273pub struct TripleRef<'a> {
274 subject: SubjectRef<'a>,
275 predicate: PredicateRef<'a>,
276 object: ObjectRef<'a>,
277}
278
279impl<'a> TripleRef<'a> {
280 pub fn new(
282 subject: SubjectRef<'a>,
283 predicate: PredicateRef<'a>,
284 object: ObjectRef<'a>,
285 ) -> Self {
286 TripleRef {
287 subject,
288 predicate,
289 object,
290 }
291 }
292
293 pub fn subject(&self) -> SubjectRef<'a> {
295 self.subject
296 }
297
298 pub fn predicate(&self) -> PredicateRef<'a> {
300 self.predicate
301 }
302
303 pub fn object(&self) -> ObjectRef<'a> {
305 self.object
306 }
307
308 pub fn to_owned(&self) -> Triple {
310 Triple {
311 subject: self.subject.to_owned(),
312 predicate: self.predicate.to_owned(),
313 object: self.object.to_owned(),
314 }
315 }
316
317 pub fn into_owned(self) -> Triple {
319 self.to_owned()
320 }
321
322 pub fn in_graph(
324 self,
325 graph_name: Option<&'a crate::model::NamedNode>,
326 ) -> crate::model::QuadRef<'a> {
327 let graph_ref = match graph_name {
328 Some(node) => crate::model::GraphNameRef::NamedNode(node),
329 None => crate::model::GraphNameRef::DefaultGraph,
330 };
331 crate::model::QuadRef::new(self.subject, self.predicate, self.object, graph_ref)
332 }
333}
334
335impl<'a> fmt::Display for TripleRef<'a> {
336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337 write!(f, "{} {} {} .", self.subject, self.predicate, self.object)
338 }
339}
340
341#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
343pub enum SubjectRef<'a> {
344 NamedNode(&'a NamedNode),
345 BlankNode(&'a BlankNode),
346 Variable(&'a Variable),
347}
348
349impl<'a> SubjectRef<'a> {
350 pub fn to_owned(&self) -> Subject {
352 match self {
353 SubjectRef::NamedNode(n) => Subject::NamedNode((*n).clone()),
354 SubjectRef::BlankNode(b) => Subject::BlankNode((*b).clone()),
355 SubjectRef::Variable(v) => Subject::Variable((*v).clone()),
356 }
357 }
358}
359
360impl<'a> fmt::Display for SubjectRef<'a> {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 match self {
363 SubjectRef::NamedNode(n) => write!(f, "{n}"),
364 SubjectRef::BlankNode(b) => write!(f, "{b}"),
365 SubjectRef::Variable(v) => write!(f, "{v}"),
366 }
367 }
368}
369
370#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
372pub enum PredicateRef<'a> {
373 NamedNode(&'a NamedNode),
374 Variable(&'a Variable),
375}
376
377impl<'a> PredicateRef<'a> {
378 pub fn to_owned(&self) -> Predicate {
380 match self {
381 PredicateRef::NamedNode(n) => Predicate::NamedNode((*n).clone()),
382 PredicateRef::Variable(v) => Predicate::Variable((*v).clone()),
383 }
384 }
385}
386
387impl<'a> fmt::Display for PredicateRef<'a> {
388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
389 match self {
390 PredicateRef::NamedNode(n) => write!(f, "{n}"),
391 PredicateRef::Variable(v) => write!(f, "{v}"),
392 }
393 }
394}
395
396#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
398pub enum ObjectRef<'a> {
399 NamedNode(&'a NamedNode),
400 BlankNode(&'a BlankNode),
401 Literal(&'a Literal),
402 Variable(&'a Variable),
403}
404
405impl<'a> ObjectRef<'a> {
406 pub fn to_owned(&self) -> Object {
408 match self {
409 ObjectRef::NamedNode(n) => Object::NamedNode((*n).clone()),
410 ObjectRef::BlankNode(b) => Object::BlankNode((*b).clone()),
411 ObjectRef::Literal(l) => Object::Literal((*l).clone()),
412 ObjectRef::Variable(v) => Object::Variable((*v).clone()),
413 }
414 }
415}
416
417impl<'a> fmt::Display for ObjectRef<'a> {
418 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
419 match self {
420 ObjectRef::NamedNode(n) => write!(f, "{n}"),
421 ObjectRef::BlankNode(b) => write!(f, "{b}"),
422 ObjectRef::Literal(l) => write!(f, "{l}"),
423 ObjectRef::Variable(v) => write!(f, "{v}"),
424 }
425 }
426}
427
428impl<'a> From<&'a Subject> for SubjectRef<'a> {
430 fn from(subject: &'a Subject) -> Self {
431 match subject {
432 Subject::NamedNode(n) => SubjectRef::NamedNode(n),
433 Subject::BlankNode(b) => SubjectRef::BlankNode(b),
434 Subject::Variable(v) => SubjectRef::Variable(v),
435 Subject::QuotedTriple(_) => panic!("QuotedTriple not supported in SubjectRef"),
436 }
437 }
438}
439
440impl<'a> From<&'a Predicate> for PredicateRef<'a> {
441 fn from(predicate: &'a Predicate) -> Self {
442 match predicate {
443 Predicate::NamedNode(n) => PredicateRef::NamedNode(n),
444 Predicate::Variable(v) => PredicateRef::Variable(v),
445 }
446 }
447}
448
449impl<'a> From<&'a Object> for ObjectRef<'a> {
450 fn from(object: &'a Object) -> Self {
451 match object {
452 Object::NamedNode(n) => ObjectRef::NamedNode(n),
453 Object::BlankNode(b) => ObjectRef::BlankNode(b),
454 Object::Literal(l) => ObjectRef::Literal(l),
455 Object::Variable(v) => ObjectRef::Variable(v),
456 Object::QuotedTriple(_) => panic!("QuotedTriple not supported in ObjectRef"),
457 }
458 }
459}
460
461impl<'a> From<&'a Triple> for TripleRef<'a> {
462 fn from(triple: &'a Triple) -> Self {
463 TripleRef {
464 subject: triple.subject().into(),
465 predicate: triple.predicate().into(),
466 object: triple.object().into(),
467 }
468 }
469}
470
471impl<'a> From<TripleRef<'a>> for Triple {
472 fn from(triple_ref: TripleRef<'a>) -> Self {
473 triple_ref.to_owned()
474 }
475}
476
477#[cfg(test)]
478mod tests {
479 use super::*;
480 use crate::model::{Literal, NamedNode};
481
482 #[test]
483 fn test_triple_creation() {
484 let subject = NamedNode::new("http://example.org/subject").unwrap();
485 let predicate = NamedNode::new("http://example.org/predicate").unwrap();
486 let object = Literal::new("object");
487
488 let triple = Triple::new(subject.clone(), predicate.clone(), object.clone());
489
490 assert!(triple.is_ground());
491 assert!(!triple.has_variables());
492 }
493
494 #[test]
495 fn test_triple_with_variable() {
496 let subject = Variable::new("x").unwrap();
497 let predicate = NamedNode::new("http://example.org/predicate").unwrap();
498 let object = Literal::new("object");
499
500 let triple = Triple::new(subject, predicate, object);
501
502 assert!(!triple.is_ground());
503 assert!(triple.has_variables());
504 }
505
506 #[test]
507 fn test_triple_display() {
508 let subject = NamedNode::new("http://example.org/s").unwrap();
509 let predicate = NamedNode::new("http://example.org/p").unwrap();
510 let object = Literal::new("o");
511
512 let triple = Triple::new(subject, predicate, object);
513 let display_str = format!("{triple}");
514
515 assert!(display_str.contains("http://example.org/s"));
516 assert!(display_str.contains("http://example.org/p"));
517 assert!(display_str.contains("\"o\""));
518 assert!(display_str.ends_with(" ."));
519 }
520
521 #[test]
522 fn test_triple_ref() {
523 let subject = NamedNode::new("http://example.org/s").unwrap();
524 let predicate = NamedNode::new("http://example.org/p").unwrap();
525 let object = Literal::new("o");
526
527 let triple = Triple::new(subject, predicate, object);
528 let triple_ref = TripleRef::from(&triple);
529 let triple_owned = triple_ref.to_owned();
530
531 assert_eq!(triple, triple_owned);
532 }
533
534 #[test]
535 fn test_pattern_matching() {
536 let subject = NamedNode::new("http://example.org/s").unwrap();
537 let predicate = NamedNode::new("http://example.org/p").unwrap();
538 let object = Literal::new("o");
539
540 let triple = Triple::new(subject.clone(), predicate.clone(), object.clone());
541
542 assert!(triple.matches_pattern(
544 Some(&Subject::NamedNode(subject.clone())),
545 Some(&Predicate::NamedNode(predicate.clone())),
546 Some(&Object::Literal(object.clone()))
547 ));
548
549 assert!(triple.matches_pattern(None, None, None));
551 assert!(triple.matches_pattern(Some(&Subject::NamedNode(subject.clone())), None, None));
552 assert!(triple.matches_pattern(None, Some(&Predicate::NamedNode(predicate.clone())), None));
553 assert!(triple.matches_pattern(None, None, Some(&Object::Literal(object.clone()))));
554
555 let different_subject = NamedNode::new("http://example.org/different").unwrap();
557 assert!(!triple.matches_pattern(Some(&Subject::NamedNode(different_subject)), None, None));
558 }
559
560 #[test]
561 fn test_triple_ordering() {
562 let subject1 = NamedNode::new("http://example.org/a").unwrap();
563 let subject2 = NamedNode::new("http://example.org/b").unwrap();
564 let predicate = NamedNode::new("http://example.org/p").unwrap();
565 let object = Literal::new("o");
566
567 let triple1 = Triple::new(subject1, predicate.clone(), object.clone());
568 let triple2 = Triple::new(subject2, predicate, object);
569
570 assert!(triple1 < triple2);
571
572 let mut triples = vec![triple2.clone(), triple1.clone()];
573 triples.sort();
574 assert_eq!(triples, vec![triple1, triple2]);
575 }
576
577 #[test]
578 fn test_triple_serialization() {
579 let subject = NamedNode::new("http://example.org/s").unwrap();
580 let predicate = NamedNode::new("http://example.org/p").unwrap();
581 let object = Literal::new("o");
582
583 let triple = Triple::new(subject, predicate, object);
584 let json = serde_json::to_string(&triple).unwrap();
585 let deserialized: Triple = serde_json::from_str(&json).unwrap();
586
587 assert_eq!(triple, deserialized);
588 }
589}