sparql_service/srdf_data/
rdf_data.rs

1use super::RdfDataError;
2use colored::*;
3use iri_s::IriS;
4use oxigraph::sparql::Query as OxQuery;
5use oxigraph::sparql::QueryResults;
6use oxigraph::store::Store;
7use oxrdf::{
8    BlankNode as OxBlankNode, Literal as OxLiteral, NamedNode as OxNamedNode, Subject as OxSubject,
9    Term as OxTerm, Triple as OxTriple,
10};
11use oxrdfio::RdfFormat;
12use prefixmap::PrefixMap;
13use sparesults::QuerySolution as SparQuerySolution;
14use srdf::FocusRDF;
15use srdf::Query;
16use srdf::QuerySolution;
17use srdf::QuerySolutions;
18use srdf::RDFFormat;
19use srdf::Rdf;
20use srdf::ReaderMode;
21use srdf::SRDFBuilder;
22use srdf::SRDFGraph;
23use srdf::SRDFSparql;
24use srdf::Sparql;
25use srdf::VarName;
26use srdf::RDF_TYPE_STR;
27use std::fmt::Debug;
28use std::io;
29use std::str::FromStr;
30
31/// Generic abstraction that represents RDF Data which can be  behind SPARQL endpoints or an in-memory graph or both
32/// The triples in RdfData are taken as the union of the triples of the endpoints and the in-memory graph
33#[derive(Clone)]
34pub struct RdfData {
35    /// Current focus node used when parsing
36    focus: Option<OxTerm>,
37
38    /// List of SPARQL endpoints
39    endpoints: Vec<SRDFSparql>,
40
41    /// In-memory graph
42    graph: Option<SRDFGraph>,
43
44    /// In-memory Store used to access the graph using SPARQL queries
45    store: Option<Store>,
46}
47
48impl Debug for RdfData {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("RdfData")
51            .field("endpoints", &self.endpoints)
52            .field("graph", &self.graph)
53            .finish()
54    }
55}
56
57impl RdfData {
58    pub fn new() -> RdfData {
59        RdfData {
60            endpoints: Vec::new(),
61            graph: None,
62            store: None,
63            focus: None,
64        }
65    }
66
67    /// Checks if the Store has been initialized
68    ///
69    /// By default, the RDF Data Store is not initialized as it is expensive and is only required for SPARQL queries
70    pub fn check_store(&mut self) -> Result<(), RdfDataError> {
71        if let Some(graph) = &self.graph {
72            if self.store.is_none() {
73                let store = Store::new()?;
74                store.bulk_loader().load_quads(graph.quads())?;
75                self.store = Some(store)
76            }
77        }
78        Ok(())
79    }
80
81    /// Creates an RdfData from an in-memory RDF Graph
82    pub fn from_graph(graph: SRDFGraph) -> Result<RdfData, RdfDataError> {
83        let store = Store::new()?;
84        store.bulk_loader().load_quads(graph.quads())?;
85        Ok(RdfData {
86            endpoints: Vec::new(),
87            graph: Some(graph),
88            store: Some(store),
89            focus: None,
90        })
91    }
92
93    // Cleans the values of endpoints and graph
94    pub fn clean_all(&mut self) {
95        self.endpoints = Vec::new();
96        self.graph = None
97    }
98
99    /// Get the in-memory graph
100    pub fn graph(&self) -> Option<&SRDFGraph> {
101        self.graph.as_ref()
102    }
103
104    /// Cleans the in-memory graph
105    pub fn clean_graph(&mut self) {
106        self.graph = None
107    }
108
109    /// Merge the in-memory graph with the graph read from a reader
110    pub fn merge_from_reader<R: io::Read>(
111        &mut self,
112        read: R,
113        format: &RDFFormat,
114        base: Option<&str>,
115        reader_mode: &ReaderMode,
116    ) -> Result<(), RdfDataError> {
117        match &mut self.graph {
118            Some(ref mut graph) => graph
119                .merge_from_reader(read, format, base, reader_mode)
120                .map_err(|e| RdfDataError::SRDFGraphError { err: e }),
121            None => {
122                let mut graph = SRDFGraph::new();
123                graph
124                    .merge_from_reader(read, format, base, reader_mode)
125                    .map_err(|e| RdfDataError::SRDFGraphError { err: e })?;
126                self.graph = Some(graph);
127                Ok(())
128            }
129        }
130    }
131
132    /// Creates an RdfData from an endpoint
133    pub fn from_endpoint(endpoint: SRDFSparql) -> RdfData {
134        RdfData {
135            endpoints: vec![endpoint],
136            graph: None,
137            store: None,
138            focus: None,
139        }
140    }
141
142    /// Adds a new endpoint to the list of endpoints
143    pub fn add_endpoint(&mut self, endpoint: SRDFSparql) {
144        // TODO: Ensure that there are no repeated endpoints
145        self.endpoints.push(endpoint);
146    }
147
148    /// Gets the PrefixMap from the in-memory graph
149    pub fn prefixmap_in_memory(&self) -> PrefixMap {
150        self.graph
151            .as_ref()
152            .map(|g| g.prefixmap())
153            .unwrap_or_default()
154    }
155
156    pub fn show_blanknode(&self, bn: &OxBlankNode) -> String {
157        let str: String = format!("{}", bn);
158        format!("{}", str.green())
159    }
160
161    pub fn show_literal(&self, lit: &OxLiteral) -> String {
162        let str: String = format!("{}", lit);
163        format!("{}", str.red())
164    }
165
166    pub fn serialize<W: io::Write>(
167        &self,
168        format: &RDFFormat,
169        writer: &mut W,
170    ) -> Result<(), RdfDataError> {
171        if let Some(graph) = &self.graph {
172            graph
173                .serialize(format, writer)
174                .map_err(|e| RdfDataError::Serializing {
175                    format: *format,
176                    error: format!("{e}"),
177                })?
178        }
179        for e in self.endpoints.iter() {
180            writeln!(writer, "Endpoint {}", e.iri())?
181        }
182        Ok(())
183    }
184}
185
186impl Default for RdfData {
187    fn default() -> Self {
188        Self::new()
189    }
190}
191
192impl Rdf for RdfData {
193    type IRI = OxNamedNode;
194    type BNode = OxBlankNode;
195    type Literal = OxLiteral;
196    type Subject = OxSubject;
197    type Term = OxTerm;
198    type Triple = OxTriple;
199    type Err = RdfDataError;
200
201    fn prefixmap(&self) -> std::option::Option<PrefixMap> {
202        self.graph.as_ref().map(|g| g.prefixmap())
203    }
204
205    fn qualify_iri(&self, node: &Self::IRI) -> String {
206        let iri = IriS::from_str(node.as_str()).unwrap();
207        if let Some(graph) = &self.graph {
208            graph.prefixmap().qualify(&iri)
209        } else {
210            for e in self.endpoints.iter() {
211                if let Some(qualified) = e.prefixmap().qualify_optional(&iri) {
212                    return qualified;
213                }
214            }
215            format!("<{node}>")
216        }
217    }
218
219    fn qualify_subject(&self, subj: &Self::Subject) -> String {
220        match subj {
221            OxSubject::BlankNode(bn) => self.show_blanknode(bn),
222            OxSubject::NamedNode(n) => self.qualify_iri(n),
223            // #[cfg(feature = "rdf-star")]
224            OxSubject::Triple(_) => unimplemented!(),
225        }
226    }
227
228    fn qualify_term(&self, term: &Self::Term) -> String {
229        match term {
230            OxTerm::BlankNode(bn) => self.show_blanknode(bn),
231            OxTerm::Literal(lit) => self.show_literal(lit),
232            OxTerm::NamedNode(n) => self.qualify_iri(n),
233            // #[cfg(feature = "rdf-star")]
234            OxTerm::Triple(_) => unimplemented!(),
235        }
236    }
237
238    fn resolve_prefix_local(
239        &self,
240        prefix: &str,
241        local: &str,
242    ) -> Result<IriS, prefixmap::PrefixMapError> {
243        if let Some(graph) = self.graph() {
244            let iri = graph.prefixmap().resolve_prefix_local(prefix, local)?;
245            Ok(iri.clone())
246        } else {
247            for e in self.endpoints.iter() {
248                if let Ok(iri) = e.prefixmap().resolve_prefix_local(prefix, local) {
249                    return Ok(iri.clone());
250                }
251            }
252            Err(prefixmap::PrefixMapError::PrefixNotFound {
253                prefix: prefix.to_string(),
254                prefixmap: PrefixMap::new(),
255            })
256        }
257    }
258}
259
260impl Sparql for RdfData {
261    fn query_select(&self, query_str: &str) -> Result<QuerySolutions<RdfData>, RdfDataError>
262    where
263        Self: Sized,
264    {
265        let mut sols: QuerySolutions<RdfData> = QuerySolutions::empty();
266        let query = OxQuery::parse(query_str, None)?;
267        if let Some(store) = &self.store {
268            let new_sol = store.query(query)?;
269            let sol = cnv_query_results(new_sol)?;
270            sols.extend(sol)
271        }
272        for endpoint in &self.endpoints {
273            let new_sols = endpoint.query_select(query_str)?;
274            let new_sols_converted: Vec<QuerySolution<RdfData>> =
275                new_sols.iter().map(cnv_sol).collect();
276            sols.extend(new_sols_converted)
277        }
278        Ok(sols)
279    }
280
281    fn query_ask(&self, _query: &str) -> Result<bool, Self::Err> {
282        todo!()
283    }
284}
285
286fn cnv_sol(sol: &QuerySolution<SRDFSparql>) -> QuerySolution<RdfData> {
287    sol.convert(|t| t.clone())
288}
289
290fn cnv_query_results(
291    query_results: QueryResults,
292) -> Result<Vec<QuerySolution<RdfData>>, RdfDataError> {
293    let mut results = Vec::new();
294    if let QueryResults::Solutions(solutions) = query_results {
295        for solution in solutions {
296            let result = cnv_query_solution(solution?);
297            results.push(result)
298        }
299    }
300    Ok(results)
301}
302
303fn cnv_query_solution(qs: SparQuerySolution) -> QuerySolution<RdfData> {
304    let mut variables = Vec::new();
305    let mut values = Vec::new();
306    for v in qs.variables() {
307        let varname = VarName::new(v.as_str());
308        variables.push(varname);
309    }
310    for t in qs.values() {
311        let term = t.clone();
312        values.push(term)
313    }
314    QuerySolution::new(variables, values)
315}
316
317fn _cnv_rdf_format(rdf_format: RDFFormat) -> RdfFormat {
318    match rdf_format {
319        RDFFormat::NTriples => RdfFormat::NTriples,
320        RDFFormat::Turtle => RdfFormat::Turtle,
321        RDFFormat::RDFXML => RdfFormat::RdfXml,
322        RDFFormat::TriG => RdfFormat::TriG,
323        RDFFormat::N3 => RdfFormat::N3,
324        RDFFormat::NQuads => RdfFormat::NQuads,
325    }
326}
327
328fn _rdf_type() -> OxNamedNode {
329    OxNamedNode::new_unchecked(RDF_TYPE_STR)
330}
331
332impl Query for RdfData {
333    fn triples(&self) -> Result<impl Iterator<Item = Self::Triple>, Self::Err> {
334        let endpoints_triples = self.endpoints.iter().flat_map(Query::triples).flatten();
335        let graph_triples = self.graph.iter().flat_map(Query::triples).flatten();
336        Ok(endpoints_triples.chain(graph_triples))
337    }
338}
339
340impl FocusRDF for RdfData {
341    fn set_focus(&mut self, focus: &Self::Term) {
342        self.focus = Some(focus.clone())
343    }
344
345    fn get_focus(&self) -> &Option<Self::Term> {
346        &self.focus
347    }
348}
349
350impl SRDFBuilder for RdfData {
351    fn empty() -> Self {
352        todo!()
353    }
354
355    fn add_base(&mut self, _base: &Option<IriS>) -> Result<(), Self::Err> {
356        todo!()
357    }
358
359    fn add_prefix(&mut self, _alias: &str, _iri: &IriS) -> Result<(), Self::Err> {
360        todo!()
361    }
362
363    fn add_prefix_map(&mut self, _prefix_map: PrefixMap) -> Result<(), Self::Err> {
364        todo!()
365    }
366
367    fn add_triple<S, P, O>(&mut self, _subj: S, _pred: P, _obj: O) -> Result<(), Self::Err>
368    where
369        S: Into<Self::Subject>,
370        P: Into<Self::IRI>,
371        O: Into<Self::Term>,
372    {
373        todo!()
374    }
375
376    fn remove_triple<S, P, O>(&mut self, _subj: S, _pred: P, _obj: O) -> Result<(), Self::Err>
377    where
378        S: Into<Self::Subject>,
379        P: Into<Self::IRI>,
380        O: Into<Self::Term>,
381    {
382        todo!()
383    }
384
385    fn add_type<S, T>(&mut self, _node: S, _type_: T) -> Result<(), Self::Err>
386    where
387        S: Into<Self::Subject>,
388        T: Into<Self::Term>,
389    {
390        todo!()
391    }
392
393    fn serialize<W: std::io::Write>(
394        &self,
395        format: &RDFFormat,
396        writer: &mut W,
397    ) -> Result<(), Self::Err> {
398        if let Some(graph) = &self.graph {
399            graph.serialize(format, writer)?;
400            Ok::<(), Self::Err>(())
401        } else {
402            Ok(())
403        }?;
404        for endpoint in &self.endpoints {
405            writeln!(writer, "Endpoint {}", endpoint.iri())?;
406        }
407        Ok(())
408    }
409
410    fn add_bnode(&mut self) -> Result<Self::BNode, Self::Err> {
411        match self.graph {
412            Some(ref mut graph) => {
413                let bnode = graph.add_bnode()?;
414                Ok(bnode)
415            }
416            None => Err(RdfDataError::BNodeNoGraph),
417        }
418    }
419}