use crate::error::ValidationError;
use rudof_rdf::rdf_core::NeighsRDF;
use rudof_rdf::rdf_core::term::{Object, Triple};
use rudof_rdf::rdf_core::vocabs::{RdfVocab, RdfsVocab};
use std::collections::{HashMap, HashSet};
#[derive(Debug, Clone, Default)]
pub(crate) struct ClassIndex {
class_instances: HashMap<Object, HashSet<Object>>,
subclass_map: HashMap<Object, HashSet<Object>>,
}
impl ClassIndex {
pub fn build<RDF: NeighsRDF>(store: &RDF) -> Result<Self, ValidationError> {
let mut class_instances: HashMap<Object, HashSet<Object>> = HashMap::new();
let mut subclass_map: HashMap<Object, HashSet<Object>> = HashMap::new();
let rdf_type: RDF::IRI = RdfVocab::rdf_type().into();
let rdfs_subclass_of: RDF::IRI = RdfsVocab::rdfs_subclass_of_str().into();
for triple in store.triples().map_err(ValidationError::new_graph_error::<RDF>)? {
let (subj, pred, obj) = triple.into_components();
if pred == rdf_type {
let class_obj = RDF::term_as_object(&obj).ok();
let instance_obj = RDF::term_as_object(&RDF::subject_as_term(&subj)).ok();
if let (Some(cls), Some(inst)) = (class_obj, instance_obj) {
class_instances.entry(cls).or_default().insert(inst);
}
} else if pred == rdfs_subclass_of {
let parent_obj = RDF::term_as_object(&obj).ok();
let child_obj = RDF::term_as_object(&RDF::subject_as_term(&subj)).ok();
if let (Some(parent), Some(child)) = (parent_obj, child_obj) {
subclass_map.entry(parent).or_default().insert(child);
}
}
}
Ok(ClassIndex {
class_instances,
subclass_map,
})
}
pub fn instances_of(&self, class: &Object) -> impl Iterator<Item = &Object> {
self.class_instances.get(class).into_iter().flat_map(|set| set.iter())
}
pub fn subclasses_of(&self, class: &Object) -> impl Iterator<Item = &Object> {
self.subclass_map.get(class).into_iter().flat_map(|set| set.iter())
}
pub fn instances_of_with_subclasses(&self, class: &Object) -> HashSet<&Object> {
let mut result: HashSet<_> = self.instances_of(class).collect();
for subclass in self.subclasses_of(class) {
for instance in self.instances_of(subclass) {
result.insert(instance);
}
}
result
}
}