use crate::hierarchy::TaxonomyHierarchy;
use ontologos_core::{EntityId, Ontology};
use crate::{Error, Result};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum QueryAtom {
Type {
var: String,
class: String,
},
Subsumed {
var: String,
superclass: String,
},
}
#[derive(Debug, Clone, Default)]
pub struct ConjunctiveQuery {
pub atoms: Vec<QueryAtom>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct QueryAnswer {
pub bindings: Vec<(String, EntityId)>,
}
pub fn evaluate(
engine: &TaxonomyHierarchy<'_>,
ontology: &Ontology,
query: &ConjunctiveQuery,
) -> Result<Vec<QueryAnswer>> {
if query.atoms.len() > 1 {
return Err(crate::Error::Parse(
"conjunctive queries with more than one atom are not supported yet".into(),
));
}
if query.atoms.is_empty() {
return Ok(Vec::new());
}
let atom = &query.atoms[0];
match atom {
QueryAtom::Type { var, class } => {
let class_id = ontology
.lookup_entity(class)
.ok_or_else(|| Error::UnknownClass(class.clone()))?;
let subs = engine.direct_subclasses(class_id)?;
let mut answers = Vec::new();
for sub in subs {
answers.push(QueryAnswer {
bindings: vec![(var.clone(), sub)],
});
}
Ok(answers)
}
QueryAtom::Subsumed { var, superclass } => {
let sup_id = ontology
.lookup_entity(superclass)
.ok_or_else(|| Error::UnknownClass(superclass.clone()))?;
let subs = engine.direct_subclasses(sup_id)?;
let mut answers = Vec::new();
for sub in subs {
answers.push(QueryAnswer {
bindings: vec![(var.clone(), sub)],
});
}
Ok(answers)
}
}
}