rdftk_core/model/statement.rs
1/*!
2* This module provides types for the RDF Statement (triple) concept.
3*
4* 1. A **statement** comprises a subject, a predicate, and an object.
5* 1. A **subject** may be a blank (unnamed) node, an IRI (named node), or a statement reference
6* according to RDF-star.
7* 1. A **predicate** is an IRI.
8* 1. An **object** may be a blank (unnamed) node, an IRI (named node), a literal value, or a statement
9* reference according to RDF-star.
10* 1. A **literal** has a string-like *lexical form* and may have an asserted data type or a language
11* identifier.
12*
13* # Example
14*
15*
16* ```rust
17* use rdftk_core::model::literal::Literal;
18* use rdftk_core::model::statement::Statement;
19* use rdftk_iri::Iri;
20* use std::str::FromStr;
21*
22* let statement = Statement::new(
23* Iri::from_str("http://en.wikipedia.org/wiki/Tony_Benn").unwrap(),
24* Iri::from_str("http://purl.org/dc/elements/1.1/title").unwrap(),
25* Literal::plain("Tony Benn"),
26* );
27* ```
28*
29*
30*/
31
32#![allow(clippy::module_name_repetitions)]
33
34use crate::error::Result;
35use crate::model::features::Featured;
36use crate::model::features::FEATURE_RDF_STAR;
37use rdftk_iri::Iri;
38use rdftk_names::rdf;
39use std::cmp::Ordering;
40use std::fmt::Formatter;
41use std::fmt::{Debug, Display};
42
43// ------------------------------------------------------------------------------------------------
44// Public Types
45// ------------------------------------------------------------------------------------------------
46
47///
48/// Simple, in-memory implementation of the `Statement` trait.
49///
50#[derive(Clone, Debug, PartialEq, Eq, Hash)]
51pub struct Statement {
52 subject: SubjectNode,
53 predicate: Iri,
54 object: ObjectNode,
55}
56
57// ------------------------------------------------------------------------------------------------
58// Implementations
59// ------------------------------------------------------------------------------------------------
60
61impl Display for Statement {
62 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63 write!(
64 f,
65 "{} <{}> {}",
66 &self.subject().to_string(),
67 &self.predicate().to_string(),
68 &self.object().to_string(),
69 )
70 }
71}
72
73// ------------------------------------------------------------------------------------------------
74
75impl PartialOrd for Statement {
76 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
77 Some(self.cmp(other))
78 }
79}
80
81impl Ord for Statement {
82 fn cmp(&self, other: &Self) -> Ordering {
83 match self.subject.cmp(&other.subject) {
84 Ordering::Equal => {}
85 ord => return ord,
86 }
87 match self.predicate.cmp(&other.predicate) {
88 Ordering::Equal => {}
89 ord => return ord,
90 }
91 self.object.cmp(&other.object)
92 }
93}
94
95// ------------------------------------------------------------------------------------------------
96
97impl Featured for Statement {
98 fn supports_feature(&self, feature: &Iri) -> bool {
99 *feature == *FEATURE_RDF_STAR || *feature == *FEATURE_STMT_OBJECT_COLLECTIONS
100 }
101}
102
103impl Statement {
104 // --------------------------------------------------------------------------------------------
105 // Constructors
106 // --------------------------------------------------------------------------------------------
107
108 pub fn new<S, O>(subject: S, predicate: Iri, object: O) -> Self
109 where
110 S: Into<SubjectNode>,
111 O: Into<ObjectNode>,
112 {
113 Self {
114 subject: subject.into(),
115 predicate,
116 object: object.into(),
117 }
118 }
119
120 pub fn rdf_type<S, O>(subject: S, object: O) -> Self
121 where
122 S: Into<SubjectNode>,
123 O: Into<ObjectNode>,
124 {
125 Self::new(subject, rdf::a_type().clone(), object)
126 }
127
128 // --------------------------------------------------------------------------------------------
129 // Components
130 // --------------------------------------------------------------------------------------------
131
132 ///
133 /// Return the subject of this statement.
134 ///
135 pub fn subject(&self) -> &SubjectNode {
136 &self.subject
137 }
138
139 ///
140 /// Set the value of this statement's subject.
141 ///
142 pub fn set_subject(&mut self, subject: SubjectNode) {
143 self.subject = subject;
144 }
145
146 ///
147 /// Return the predicate of this statement.
148 ///
149 pub fn predicate(&self) -> &Iri {
150 &self.predicate
151 }
152
153 ///
154 /// Set the value of this statement's predicate.
155 ///
156 pub fn set_predicate(&mut self, predicate: Iri) {
157 self.predicate = predicate;
158 }
159
160 ///
161 /// Return the object of this statement.
162 ///
163 pub fn object(&self) -> &ObjectNode {
164 &self.object
165 }
166
167 ///
168 /// Set the value of this statement's object.
169 ///
170 pub fn set_object(&mut self, object: ObjectNode) {
171 self.object = object;
172 }
173
174 // --------------------------------------------------------------------------------------------
175 // Other
176 // --------------------------------------------------------------------------------------------
177
178 ///
179 /// This statement is considered nested if *either* subject or object is itself a statement
180 /// ([RDF-star](https://w3c.github.io/rdf-star/cg-spec/editors_draft.html))
181 ///
182 pub fn is_nested(&self) -> bool {
183 self.subject().is_statement() || self.object().is_statement()
184 }
185
186 ///
187 /// Reify a single statement, returning the list of resulting statements.
188 ///
189 pub fn reify(&self) -> Result<(SubjectNode, Vec<Self>)> {
190 let mut statements: Vec<Self> = Default::default();
191 let new_subject: SubjectNode = BlankNode::generate().into();
192 statements.push(Self::new(
193 new_subject.clone(),
194 rdf::a_type().clone(),
195 rdf::statement().clone(),
196 ));
197 if let Some(statement) = self.subject().as_statement() {
198 let nested = statement.reify()?;
199 statements.extend(nested.1);
200 statements.push(Self::new(
201 new_subject.clone(),
202 rdf::subject().clone(),
203 nested.0.to_object(),
204 ));
205 } else {
206 statements.push(Self::new(
207 new_subject.clone(),
208 rdf::subject().clone(),
209 self.subject().to_object(),
210 ));
211 }
212 statements.push(Self::new(
213 new_subject.clone(),
214 rdf::predicate().clone(),
215 self.predicate().clone(),
216 ));
217 if let Some(statement) = self.object().as_statement() {
218 let nested = statement.reify()?;
219 statements.extend(nested.1);
220 statements.push(Self::new(
221 new_subject.clone(),
222 rdf::object().clone(),
223 nested.0.to_object(),
224 ));
225 } else {
226 // TODO: check for ObjectNode::Collection
227 statements.push(Self::new(
228 new_subject.clone(),
229 rdf::object().clone(),
230 self.object().clone(),
231 ));
232 }
233 Ok((new_subject, statements))
234 }
235}
236
237// ------------------------------------------------------------------------------------------------
238// Modules
239// ------------------------------------------------------------------------------------------------
240
241mod bnode;
242pub use bnode::*;
243
244mod collection;
245pub use collection::*;
246
247mod subject;
248pub use subject::*;
249
250mod object;
251pub use object::*;
252
253use super::features::FEATURE_STMT_OBJECT_COLLECTIONS;