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;
45pub use _macro::*;
46mod _namespace;
47pub use _namespace::*;
48mod _term;
49pub use _term::*;
50
51/// The standard `rdf:` namespace.
52///
53/// NB: since `type` is a reserved keyword in Rust,
54/// the term `rdf:type` spells `rdf::type_` (with a trailing underscore).
55///
56pub mod rdf {
57 namespace!(
58 "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
59 // classes
60 Alt,
61 Bag,
62 List,
63 PlainLiteral,
64 Property,
65 Seq,
66 Statement,
67 // datatypes
68 HTML,
69 JSON,
70 langString,
71 XMLLiteral,
72 // properties
73 direction,
74 first,
75 language,
76 object,
77 predicate,
78 rest,
79 subject,
80 value,
81 // individuals
82 nil,
83 // core syntax terms
84 RDF,
85 ID,
86 Description,
87 about,
88 parseType,
89 resource,
90 li,
91 nodeID,
92 datatype,
93 bagID,
94 aboutEach,
95 aboutEachPrefix;
96 // 'type' is a Rust keyword, so we use 'type_' instead
97 type_, "type"
98 );
99}
100
101/// The standard `xsd:` namespace.
102#[rustfmt::skip]
103pub mod xsd {
104 namespace!(
105 "http://www.w3.org/2001/XMLSchema#",
106 anyType,
107 anySimpleType,
108 duration,
109 dateTime,
110 time,
111 date,
112 gYearMonth,
113 gYear,
114 gMonthDay,
115 gDay,
116 gMonth,
117 boolean,
118 base64Binary,
119 hexBinary,
120 float,
121 double,
122 anyURI,
123 QName,
124 NOTATION,
125 string,
126 normalizedString,
127 token,
128 language,
129 Name,
130 NCName,
131 ID,
132 IDREF,
133 IDREFS,
134 ENTITY,
135 ENTITIES,
136 NMTOKEN,
137 NMTOKENS,
138 decimal,
139 integer,
140 nonPositiveInteger,
141 negativeInteger,
142 long,
143 int,
144 short,
145 byte,
146 nonNegativeInteger,
147 unsignedLong,
148 unsignedInt,
149 unsignedShort,
150 unsignedByte,
151 positiveInteger
152 );
153}
154
155/// The standard `rdfs:` namespace.
156pub mod rdfs {
157 namespace!(
158 "http://www.w3.org/2000/01/rdf-schema#",
159 // types
160 Class,
161 Container,
162 ContainerMembershipProperty,
163 Datatype,
164 Literal,
165 Resource,
166 // semantic properties
167 domain,
168 range,
169 subClassOf,
170 subPropertyOf,
171 // documentation properties
172 comment,
173 isDefinedBy,
174 label,
175 member,
176 seeAlso
177 );
178}
179
180/// The standard `xml:` namespace
181pub mod xml {
182 namespace!(
183 "http://www.w3.org/XML/1998/namespace#",
184 lang,
185 space,
186 base,
187 id,
188 // Jon Bosak
189 Father
190 );
191}
192
193/// The standard `owl:` namespace
194pub mod owl {
195 namespace!(
196 "http://www.w3.org/2002/07/owl#",
197 Nothing,
198 Thing,
199 // Classes
200 AllDifferent,
201 AllDisjointClasses,
202 AnnotationProperty,
203 Class,
204 DatatypeProperty,
205 FunctionalProperty,
206 InverseFunctionalProperty,
207 IrreflexiveProperty,
208 ObjectProperty,
209 SymmetricProperty,
210 TransitiveProperty,
211 // Properties
212 allValuesFrom,
213 assertionProperty,
214 complementOf,
215 differentFrom,
216 disjointWith,
217 distinctMembers,
218 equivalentClass,
219 equivalentProperty,
220 intersectionOf,
221 inverseOf,
222 maxCardinality,
223 maxQualifiedCardinality,
224 members,
225 onClass,
226 oneOf,
227 onProperty,
228 propertyChainAxiom,
229 propertyDisjointWith,
230 sameAs,
231 someValuesFrom,
232 sourceIndividual,
233 targetIndividual,
234 targetValue,
235 unionOf
236 );
237}
238
239#[cfg(test)]
240mod test {
241 // Nothing really worth testing here
242 use super::*;
243 use std::rc::Rc;
244
245 #[test]
246 fn test_same_term() {
247 let ns1 = Namespace::new("http://schema.org/").unwrap();
248 let ns2 = Namespace::new(Rc::from("http://schema.org/")).unwrap();
249
250 assert_eq!(
251 ns1.get("name").unwrap().to_string(),
252 ns1.get("name").unwrap().to_string()
253 );
254 assert_eq!(
255 ns2.get("name").unwrap().to_string(),
256 ns2.get("name").unwrap().to_string()
257 );
258 assert_eq!(
259 ns1.get("name").unwrap().to_string(),
260 ns2.get("name").unwrap().to_string()
261 );
262 }
263
264 #[test]
265 fn test_different_terms() {
266 let ns1 = Namespace::new("http://schema.org/").unwrap();
267 assert_ne!(
268 ns1.get("name").unwrap().to_string(),
269 ns1.get("nam").unwrap().to_string()
270 );
271 }
272
273 #[test]
274 fn test_invalid_namespace() {
275 assert!(Namespace::new("http://schema.org ").is_err());
276 }
277
278 #[test]
279 fn test_invalid_suffix() {
280 let ns1 = Namespace::new("http://schema.org/").unwrap();
281 assert!(ns1.get("name ").is_err());
282 }
283}