ekg_identifier/
namespace.rs1use {
2 crate::NamespaceIRI,
3 std::{
4 fmt::{Display, Formatter},
5 hash::{Hash, Hasher},
6 },
7};
8
9#[derive(Debug, Clone)]
18pub struct Namespace {
19 pub name: String,
21 pub iri: crate::TBoxNamespaceIRI,
23}
24
25impl Eq for Namespace {}
26
27impl PartialEq for Namespace {
28 fn eq(&self, other: &Self) -> bool {
29 self.name == other.name && self.iri.as_str() == other.iri.as_str()
30 }
31}
32
33impl Hash for Namespace {
34 fn hash<H: Hasher>(&self, state: &mut H) { self.name.hash(state); }
35}
36
37impl Display for Namespace {
38 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
40 write!(f, "{} <{}>", self.name.as_str(), self.iri)
41 }
42}
43
44impl Namespace {
45 pub fn declare(name: &str, iri: crate::TBoxNamespaceIRI) -> Result<Self, ekg_error::Error> {
46 match iri.to_string().chars().last() {
47 Some('/') | Some('#') => Ok(Self { name: name.to_string(), iri }),
48 _ => {
49 tracing::error!("{} does not end with either / or #", iri);
50 Err(ekg_error::Error::IncorrectBaseIRI { iri: iri.to_string() })
51 },
52 }
53 }
54
55 pub fn declare_iref_iri(name: &str, iri: &iref::Iri) -> Result<Self, ekg_error::Error> {
59 match iri.to_string().chars().last() {
60 Some('/') | Some('#') => Ok(Self { name: name.to_string(), iri: iri.try_into()? }),
61 _ => {
62 tracing::error!("{} does not end with either / or #", iri);
63 Err(ekg_error::Error::IncorrectBaseIRI { iri: iri.to_string() })
64 },
65 }
66 }
67
68 pub fn declare_from_str(name: &str, iri: &str) -> Result<Self, ekg_error::Error> {
69 Self::declare(name, iri.try_into()?)
70 }
71
72 pub fn with_local_name(
76 &self,
77 name: &str,
78 ) -> Result<iri_string::types::IriReferenceString, ekg_error::Error> {
79 let iri_str = match self.iri.to_string().chars().last().unwrap() {
80 '/' | '#' => format!("{}{name}", self.iri),
81 _ => {
82 panic!("{} does not end with either / or #", self.iri)
83 },
84 };
85
86 Ok(iri_string::types::IriReferenceString::try_from(
87 iri_str,
88 )?)
89 }
90
91 #[inline]
92 pub fn is_in_namespace(&self, iri: &str) -> bool { self.iri.is_in_namespace(iri) }
93
94 pub fn as_sparql_prefix(&self) -> String { format!("PREFIX {} <{}>", self.name, self.iri) }
96
97 pub fn as_turtle_prefix(&self) -> String { format!("@prefix {} <{}> .", self.name, self.iri) }
99}
100
101#[cfg(test)]
102mod tests {
103 #[test_log::test]
104 fn test_a_prefix() -> Result<(), ekg_error::Error> {
105 let namespace = crate::Namespace::declare(
106 "test:",
107 iri_string::types::IriReferenceString::try_from("http://whatever.kom/test#")
108 .unwrap()
109 .into(),
110 )
111 .unwrap();
112 let x = namespace.with_local_name("abc")?;
113
114 assert_eq!(
115 x.to_string().as_str(),
116 "http://whatever.kom/test#abc"
117 );
118 Ok(())
119 }
120
121 #[test_log::test]
122 fn test_b_prefix() -> Result<(), ekg_error::Error> {
123 let namespace = crate::Namespace::declare(
124 "test:",
125 iri_string::types::IriReferenceString::try_from("http://whatever.kom/test/")
126 .unwrap()
127 .into(),
128 )
129 .unwrap();
130 let x = namespace.with_local_name("abc")?;
131
132 assert_eq!(
133 x.to_string().as_str(),
134 "http://whatever.kom/test/abc"
135 );
136 Ok(())
137 }
138
139 #[test_log::test]
140 fn test_iri_string() -> Result<(), ekg_error::Error> {
141 let x = iri_string::types::IriReferenceString::try_from("http://whatever.kom/test/abc#")?;
142 assert_eq!(x.as_str(), "http://whatever.kom/test/abc#");
143
144 let x = iri_string::types::IriReferenceString::try_from("http://whatever.kom/test/abc/")?;
145 assert_eq!(x.as_str(), "http://whatever.kom/test/abc/");
146 Ok(())
147 }
148}