use crate::errors::QueryError;
use rudof_rdf::rdf_core::{Rdf, query::QuerySolutions, term::Object};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use sparql_service::RdfData;
use std::collections::BTreeMap;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
pub struct Bindings {
variables: Vec<String>,
rows: Vec<BTreeMap<String, Object>>,
}
impl Bindings {
pub fn variables(&self) -> &[String] {
&self.variables
}
pub fn rows(&self) -> &[BTreeMap<String, Object>] {
&self.rows
}
pub fn count(&self) -> usize {
self.rows.len()
}
}
impl TryFrom<&QuerySolutions<RdfData>> for Bindings {
type Error = QueryError;
fn try_from(solutions: &QuerySolutions<RdfData>) -> std::result::Result<Self, Self::Error> {
let variables: Vec<String> = solutions
.iter()
.next()
.map(|solution| solution.variables_iter().map(|var| var.as_str().to_string()).collect())
.unwrap_or_default();
let mut rows = Vec::with_capacity(solutions.count());
for solution in solutions.iter() {
let mut row = BTreeMap::new();
for (column, variable) in variables.iter().enumerate() {
if let Some(term) = solution.find_solution(column) {
let object = RdfData::term_as_object(term)
.map_err(|e| QueryError::FailedQualifyingSolution { error: e.to_string() })?;
row.insert(variable.clone(), object);
}
}
rows.push(row);
}
Ok(Bindings { variables, rows })
}
}