ekg_namespace/
class.rs

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