ekg_metadata/
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, PartialEq, Eq, Hash, 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<iri_string::types::IriReferenceString, ekg_error::Error> {
30        Ok(iri_string::types::IriReferenceString::try_from(
31            format!("{}{}", self.namespace.iri, self.local_name),
32        )?)
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 {
51        if self.local_name.ends_with('y') {
52            let regex = fancy_regex::Regex::new(r"y$").expect("Failed to create regex");
53            regex.replace(self.local_name.as_str(), "ies").to_string()
54        } else {
55            format!("{}s", self.local_name)
56        }
57    }
58
59    // TODO: Make this slightly smarter
60
61    pub fn is_literal(&self, literal: &Literal) -> bool {
62        if let Some(that_iri) = literal.as_iri_ref() {
63            if let Ok(this_iri) = self.as_iri() {
64                that_iri == this_iri
65            } else {
66                let iri = self.to_string();
67                literal.to_string() == iri
68            }
69        } else {
70            false
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use {
78        crate::{class::Class, DataType, Literal},
79        super::Namespace,
80    };
81
82    #[test]
83    fn test_a_class_01() {
84        let namespace = Namespace::declare(
85            "test:",
86            "https://whatever.com/test#".to_string().try_into().unwrap(),
87            // &iri_string::types::IriReferenceString::try_from("https://whatever.com/test#").unwrap(),
88        )
89        .unwrap();
90        let class = Class::declare(namespace, "SomeClass");
91        let s = format!("{:}", class);
92        assert_eq!(s, "test:SomeClass")
93    }
94
95    #[test]
96    fn test_a_class_02() {
97        let namespace = Namespace::declare(
98            "test:",
99            iri_string::types::IriReferenceString::try_from("https://whatever.com/test#")
100                .unwrap()
101                .try_into()
102                .unwrap(),
103        )
104        .unwrap();
105        let class = Class::declare(namespace, "SomeClass");
106        let s = format!("{}", class.as_iri().unwrap());
107        assert_eq!(s, "https://whatever.com/test#SomeClass");
108    }
109
110    #[test]
111    fn test_is_literal() {
112        let namespace = Namespace::declare(
113            "test:",
114            iri_string::types::IriReferenceString::try_from("https://whatever.com/test#")
115                .unwrap()
116                .try_into()
117                .unwrap(),
118        )
119        .unwrap();
120        let class = Class::declare(namespace, "SomeClass");
121        let literal = Literal::from_type_and_buffer(
122            DataType::AnyUri,
123            "https://whatever.com/test#SomeClass",
124            None,
125        )
126        .unwrap();
127        assert!(literal.is_some());
128        assert_eq!(
129            class.as_iri().unwrap().to_string().as_str(),
130            "https://whatever.com/test#SomeClass"
131        );
132        assert!(class.is_literal(&literal.unwrap()))
133    }
134}