pub mod doc;
pub mod http;
pub mod table;
use crate::table::{Table, Variable};
use async_trait::async_trait;
use rdf::node::Node;
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub struct Resource(String);
impl From<&str> for Resource {
fn from(s: &str) -> Self {
Resource(s.to_string())
}
}
pub enum Graph {
Default,
Named(Resource),
}
#[derive(Debug)]
pub enum DataFile {
Turtle { content: Vec<u8> },
RdfXml { content: Vec<u8> },
}
impl DataFile {
pub fn unsafe_from_turtle(s: &str) -> Self {
DataFile::Turtle {
content: Vec::from(s.as_bytes()),
}
}
}
pub struct Selection {
sparql_value: String,
}
impl Selection {
pub fn of_triples() -> Selection {
Selection::unsafe_from("SELECT ?s ?p ?o WHERE { ?s ?p ?o } LIMIT 25")
}
pub fn of_graphs() -> Selection {
Selection::unsafe_from("SELECT DISTINCT ?graph WHERE { GRAPH ?graph { ?s ?p ?o } }")
}
pub fn of_resources_from_named_graphs() -> Selection {
Selection::unsafe_from("SELECT ?s WHERE { GRAPH ?g { ?s ?p ?o } }")
}
pub fn of_relations_from(resource: &Resource) -> Selection {
Selection::unsafe_from(&format!(
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?predicate ?predicate_label ?object ?object_label
WHERE {{
GRAPH ?g1 {{ <{}> ?predicate ?object }}
OPTIONAL {{ GRAPH ?g2 {{ ?predicate rdfs:label ?predicate_label }} }}
OPTIONAL {{ GRAPH ?g3 {{ ?object rdfs:label ?object_label }} }}
}}",
resource.0
))
}
pub fn of_relations_to(resource: &Resource) -> Selection {
Selection::unsafe_from(&format!(
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?subject ?subject_label ?predicate ?predicate_label
WHERE {{
GRAPH ?g1 {{ ?subject ?predicate <{}> }}
OPTIONAL {{ GRAPH ?g2 {{ ?predicate rdfs:label ?predicate_label }} }}
OPTIONAL {{ GRAPH ?g3 {{ ?subject rdfs:label ?subject_label }} }}
}}",
resource.0
))
}
pub fn of_resources_with_labels() -> Selection {
Selection::unsafe_from(
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?resource ?label
WHERE {
GRAPH ?graph1 {
{ ?resource ?predicate ?object }
UNION
{ ?subject ?resource ?object }
UNION
{ ?subject ?predicate ?resource }
} .
OPTIONAL {
GRAPH ?graph3 { ?resource rdfs:label ?label }
} .
FILTER ( isURI(?resource) )
}",
)
}
pub fn unsafe_from(value: &str) -> Selection {
Selection {
sparql_value: value.to_string(),
}
}
}
pub struct DescribeQuery {
sparql_value: String,
}
impl DescribeQuery {
pub fn unsafe_from(value: &str) -> DescribeQuery {
DescribeQuery {
sparql_value: value.to_string(),
}
}
}
#[async_trait]
pub trait GraphStore {
async fn import(&self, graph: Graph, file: DataFile);
async fn select(&self, query: Selection) -> Table<Node>;
async fn describe(&self, query: DescribeQuery) -> rdf::graph::Graph;
async fn describe_everything(&self) -> rdf::graph::Graph {
let graphs = self.select(Selection::of_graphs()).await;
let from: String = graphs
.bindings
.iter()
.map(|b| {
format!(
"FROM <{}>",
match b.get(&Variable::from("graph")) {
Some(rdf::node::Node::UriNode { uri: id }) => id.to_string(),
_ => panic!("Unexpected node"),
}
)
})
.collect::<Vec<_>>()
.join(" ");
let query =
DescribeQuery::unsafe_from(&format!("DESCRIBE ?x {} WHERE {{ ?x ?y ?z }}", from));
self.describe(query).await
}
}