sophia_api/ns.rs
1//! Standard and custom namespaces.
2//!
3//! This module provides:
4//! * the [`Namespace`](struct.Namespace.html) type for defining custom dynamic namespace;
5//! * the [`namespace`](crate::namespace) macro, for defning custom static namespaces;
6//! * modules corresponding to the most common namespaces
7//! (generated via the [`namespace`](crate::namespace) macro).
8//!
9//! # Example use
10//! ```
11//! use sophia_api::ns::{Namespace, rdf, rdfs, xsd};
12//!
13//! let schema = Namespace::new("http://schema.org/").unwrap();
14//! let s_name = schema.get("name").unwrap();
15//!
16//! // you can now populate a graph like this:
17//! let mut g = vec![];
18//! g.push([&s_name, &rdf::type_, &rdf::Property]);
19//! g.push([&s_name, &rdfs::range, &xsd::string]);
20//! ```
21//!
22//! # Datatyped literals
23//!
24//! Note also that the terms generated via the [`namespace`](crate::namespace) macro
25//! can be used to easily produce datatyped literals,
26//! by simply "multiplying" a string by its datatype:
27//!
28//! ```
29//! # use sophia_api::{term::Term, ns::xsd};
30//! let date = "2023-11-15" * xsd::date ;
31//! assert!(date.is_literal());
32//! assert_eq!(date.lexical_form().unwrap(), "2023-11-15");
33//! assert_eq!(date.datatype().unwrap(), xsd::date.iri().unwrap());
34//! ```
35use mownstr::MownStr;
36use sophia_iri::InvalidIri;
37use std::borrow::Borrow;
38use std::fmt;
39
40// rexport is necessary to ensure that the macros work.
41pub use sophia_iri::IriRef;
42
43#[macro_use]
44mod _macro;
45mod _namespace;
46pub use _namespace::*;
47mod _term;
48pub use _term::*;
49
50/// The standard `rdf:` namespace.
51///
52/// NB: since `type` is a reserved keyword in Rust,
53/// the term `rdf:type` spells `rdf::type_` (with a trailing underscore).
54///
55pub mod rdf {
56 namespace!(
57 "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
58 // classes
59 Alt,
60 Bag,
61 List,
62 PlainLiteral,
63 Property,
64 Seq,
65 Statement,
66 // datatypes
67 HTML,
68 JSON,
69 langString,
70 XMLLiteral,
71 // properties
72 direction,
73 first,
74 language,
75 object,
76 predicate,
77 rest,
78 subject,
79 value,
80 // individuals
81 nil,
82 // core syntax terms
83 RDF,
84 ID,
85 Description,
86 about,
87 parseType,
88 resource,
89 li,
90 nodeID,
91 datatype,
92 bagID,
93 aboutEach,
94 aboutEachPrefix;
95 // 'type' is a Rust keyword, so we use 'type_' instead
96 type_, "type"
97 );
98}
99
100/// The standard `xsd:` namespace.
101#[rustfmt::skip]
102pub mod xsd {
103 namespace!(
104 "http://www.w3.org/2001/XMLSchema#",
105 anyType,
106 anySimpleType,
107 duration,
108 dateTime,
109 time,
110 date,
111 gYearMonth,
112 gYear,
113 gMonthDay,
114 gDay,
115 gMonth,
116 boolean,
117 base64Binary,
118 hexBinary,
119 float,
120 double,
121 anyURI,
122 QName,
123 NOTATION,
124 string,
125 normalizedString,
126 token,
127 language,
128 Name,
129 NCName,
130 ID,
131 IDREF,
132 IDREFS,
133 ENTITY,
134 ENTITIES,
135 NMTOKEN,
136 NMTOKENS,
137 decimal,
138 integer,
139 nonPositiveInteger,
140 negativeInteger,
141 long,
142 int,
143 short,
144 byte,
145 nonNegativeInteger,
146 unsignedLong,
147 unsignedInt,
148 unsignedShort,
149 unsignedByte,
150 positiveInteger
151 );
152}
153
154/// The standard `rdfs:` namespace.
155pub mod rdfs {
156 namespace!(
157 "http://www.w3.org/2000/01/rdf-schema#",
158 // types
159 Class,
160 Container,
161 ContainerMembershipProperty,
162 Datatype,
163 Literal,
164 Resource,
165 // semantic properties
166 domain,
167 range,
168 subClassOf,
169 subPropertyOf,
170 // documentation properties
171 comment,
172 isDefinedBy,
173 label,
174 member,
175 seeAlso
176 );
177}
178
179/// The standard `xml:` namespace
180pub mod xml {
181 namespace!(
182 "http://www.w3.org/XML/1998/namespace#",
183 lang,
184 space,
185 base,
186 id,
187 // Jon Bosak
188 Father
189 );
190}
191
192/// The standard `owl:` namespace
193pub mod owl {
194 namespace!(
195 "http://www.w3.org/2002/07/owl#",
196 Nothing,
197 Thing,
198 // Classes
199 AllDifferent,
200 AllDisjointClasses,
201 AnnotationProperty,
202 Class,
203 DatatypeProperty,
204 FunctionalProperty,
205 InverseFunctionalProperty,
206 IrreflexiveProperty,
207 ObjectProperty,
208 SymmetricProperty,
209 TransitiveProperty,
210 // Properties
211 allValuesFrom,
212 assertionProperty,
213 complementOf,
214 differentFrom,
215 disjointWith,
216 distinctMembers,
217 equivalentClass,
218 equivalentProperty,
219 intersectionOf,
220 inverseOf,
221 maxCardinality,
222 maxQualifiedCardinality,
223 members,
224 onClass,
225 oneOf,
226 onProperty,
227 propertyChainAxiom,
228 propertyDisjointWith,
229 sameAs,
230 someValuesFrom,
231 sourceIndividual,
232 targetIndividual,
233 targetValue,
234 unionOf
235 );
236}
237
238#[cfg(test)]
239mod test {
240 // Nothing really worth testing here
241 use super::*;
242 use std::rc::Rc;
243
244 #[test]
245 fn test_same_term() {
246 let ns1 = Namespace::new("http://schema.org/").unwrap();
247 let ns2 = Namespace::new(Rc::from("http://schema.org/")).unwrap();
248
249 assert_eq!(
250 ns1.get("name").unwrap().to_string(),
251 ns1.get("name").unwrap().to_string()
252 );
253 assert_eq!(
254 ns2.get("name").unwrap().to_string(),
255 ns2.get("name").unwrap().to_string()
256 );
257 assert_eq!(
258 ns1.get("name").unwrap().to_string(),
259 ns2.get("name").unwrap().to_string()
260 );
261 }
262
263 #[test]
264 fn test_different_terms() {
265 let ns1 = Namespace::new("http://schema.org/").unwrap();
266 assert_ne!(
267 ns1.get("name").unwrap().to_string(),
268 ns1.get("givenName").unwrap().to_string()
269 );
270 }
271
272 #[test]
273 fn test_invalid_namespace() {
274 assert!(Namespace::new("http://schema.org ").is_err());
275 }
276
277 #[test]
278 fn test_invalid_suffix() {
279 let ns1 = Namespace::new("http://schema.org/").unwrap();
280 assert!(ns1.get("name ").is_err());
281 }
282}