rdf_store_rs/
class.rs

1// Copyright (c) 2018-2023, agnos.ai UK Ltd, all rights reserved.
2//---------------------------------------------------------------
3
4use crate::{Literal, Namespace, RDFStoreError};
5
6/// The `Class` struct represents an RDFS or OWL class identifier
7/// consisting of a [`Namespace`] (i.e. a namespace) and a "local name".
8#[derive(Debug, Clone)]
9pub struct Class {
10    pub namespace:  Namespace,
11    pub local_name: String,
12}
13
14impl std::fmt::Display for Class {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        write!(
17            f,
18            "{}{}",
19            self.namespace.name.as_str(),
20            self.local_name.as_str()
21        )
22    }
23}
24
25impl Class {
26    pub fn declare(namespace: Namespace, local_name: &str) -> Self {
27        Self { namespace, local_name: local_name.to_string() }
28    }
29
30    pub fn as_iri(&self) -> Result<iref::IriBuf, RDFStoreError> {
31        let iri = iref::IriBuf::try_from(format!("{}{}", self.namespace.iri.as_str(), self.local_name.as_str()))?;
32        Ok(iri)
33    }
34
35    #[allow(clippy::needless_lifetimes)]
36    pub fn display_turtle<'a>(&'a self) -> impl std::fmt::Display + 'a {
37        struct TurtleClass<'a>(&'a Class);
38        impl<'a> std::fmt::Display for TurtleClass<'a> {
39            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
40                write!(
41                    f,
42                    "{}{}",
43                    self.0.namespace.name, self.0.local_name
44                )
45            }
46        }
47        TurtleClass(self)
48    }
49
50    pub fn plural_label(&self) -> String { format!("{}s", self.local_name) }
51
52    // TODO: Make this slightly smarter
53
54    pub fn is_literal(&self, literal: &Literal) -> bool {
55        if let Some(that_iri) = literal.as_iri() {
56            if let Ok(this_iri) = self.as_iri() {
57                that_iri == this_iri.as_iri()
58            } else {
59                let iri = self.to_string();
60                literal.to_string() == iri
61            }
62        } else {
63            false
64        }
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use {
71        super::Namespace,
72        crate::{class::Class, DataType, Literal},
73    };
74
75    #[test]
76    fn test_a_class_01() {
77        let namespace = Namespace::declare(
78            "test:",
79            iref::Iri::new("https://whatever.com/test#").unwrap(),
80        );
81        let class = Class::declare(namespace, "SomeClass");
82        let s = format!("{:}", class);
83        assert_eq!(s, "test:SomeClass")
84    }
85
86    #[test]
87    fn test_a_class_02() {
88        let namespace = Namespace::declare(
89            "test:",
90            iref::Iri::new("https://whatever.com/test#").unwrap(),
91        );
92        let class = Class::declare(namespace, "SomeClass");
93        let s = format!("{}", class.as_iri().unwrap());
94        assert_eq!(s, "https://whatever.com/test#SomeClass");
95    }
96
97    #[test]
98    fn test_is_literal() {
99        let namespace = Namespace::declare(
100            "test:",
101            iref::Iri::new("https://whatever.com/test#").unwrap(),
102        );
103        let class = Class::declare(namespace, "SomeClass");
104        let literal = Literal::from_type_and_buffer(
105            DataType::AnyUri,
106            "https://whatever.com/test#SomeClass",
107            None,
108        )
109        .unwrap();
110        assert!(literal.is_some());
111        assert_eq!(
112            class.as_iri().unwrap().as_str(),
113            "https://whatever.com/test#SomeClass"
114        );
115        assert!(class.is_literal(&literal.unwrap()))
116    }
117}