use crate::model::{Triple, NamedGraph, JsonLdDocument};
use std::collections::HashMap;
use anyhow::Result;
#[derive(Debug, Clone, Default)]
pub struct GraphStore {
graphs: HashMap<String, NamedGraph>,
default_graph: NamedGraph,
}
impl GraphStore {
pub fn new() -> Self {
Self {
graphs: HashMap::new(),
default_graph: NamedGraph {
name: "default".to_string(),
triples: Vec::new(),
},
}
}
pub fn add_triple(&mut self, triple: Triple) {
self.default_graph.triples.push(triple);
}
pub fn add_triple_to_graph(&mut self, graph_name: &str, triple: Triple) {
self.graphs
.entry(graph_name.to_string())
.or_insert_with(|| NamedGraph {
name: graph_name.to_string(),
triples: Vec::new(),
})
.triples
.push(triple);
}
pub fn add_triples_to_graph(&mut self, graph_name: &str, triples: Vec<Triple>) {
self.graphs
.entry(graph_name.to_string())
.or_insert_with(|| NamedGraph {
name: graph_name.to_string(),
triples: Vec::new(),
})
.triples
.extend(triples);
}
pub fn get_default_graph(&self) -> &NamedGraph {
&self.default_graph
}
pub fn get_graph(&self, name: &str) -> Option<&NamedGraph> {
self.graphs.get(name)
}
pub fn graph_names(&self) -> Vec<String> {
self.graphs.keys().cloned().collect()
}
pub fn find_triples(&self, subject: Option<&str>, predicate: Option<&str>, object: Option<&str>) -> Vec<&Triple> {
let mut results = Vec::new();
for triple in &self.default_graph.triples {
if self.matches_pattern(triple, subject, predicate, object) {
results.push(triple);
}
}
for graph in self.graphs.values() {
for triple in &graph.triples {
if self.matches_pattern(triple, subject, predicate, object) {
results.push(triple);
}
}
}
results
}
fn matches_pattern(&self, triple: &Triple, subject: Option<&str>, predicate: Option<&str>, object: Option<&str>) -> bool {
if let Some(s) = subject {
if triple.subject != s {
return false;
}
}
if let Some(p) = predicate {
if triple.predicate != p {
return false;
}
}
if let Some(o) = object {
if triple.object != o {
return false;
}
}
true
}
pub fn to_jsonld(&self) -> Result<JsonLdDocument> {
let mut graph = Vec::new();
for triple in &self.default_graph.triples {
let node = serde_json::json!({
"@id": triple.subject,
triple.predicate.clone(): triple.object
});
graph.push(node);
}
for named_graph in self.graphs.values() {
for triple in &named_graph.triples {
let node = serde_json::json!({
"@id": triple.subject,
triple.predicate.clone(): triple.object
});
graph.push(node);
}
}
Ok(JsonLdDocument {
context: serde_json::json!({
"@vocab": "https://w3id.org/security#",
"rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs": "http://www.w3.org/2000/01/rdf-schema#"
}),
graph: Some(graph),
data: HashMap::new(),
})
}
pub fn clear(&mut self) {
self.graphs.clear();
self.default_graph.triples.clear();
}
}