use rayon::iter::ParallelIterator; use std::collections::{HashMap, HashSet}; use oxigraph::model::{Graph, NamedNode, TermRef, NamedOrBlankNodeRef, NamedNodeRef}; use rayon::iter::IntoParallelRefIterator; use gl_search::{Field, OwnedValue, Schema}; use crate::class::Class; use crate::{helpers, vocab, CurieHelper}; use crate::language::LanguageCondition; use crate::ontology::ResourceDescription; pub struct Indexer<'a> { language: LanguageCondition, curie_helper: &'a CurieHelper, } impl<'a> Indexer<'a> { pub fn new(language: LanguageCondition, curie_helper: &'a CurieHelper) -> Self { Self { language, curie_helper, } } fn extract_string(&self, graph: &Graph, subject: NamedNodeRef, predicate: NamedNodeRef) -> OwnedValue { graph.object_for_subject_predicate(subject, predicate) .filter(|term| self.language.primary_matches_term(*term)) .and_then(helpers::term_ref_as_str) .map(String::from) .map(OwnedValue::Str) .unwrap_or_else(|| OwnedValue::Null) } fn person(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap { HashMap::from_iter([ ( Schema::field("given_name", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdaad::GIVEN_NAME), ), ( Schema::field("surname", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdaad::SURNAME), ), ]) } fn corporate_body(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap { HashMap::from_iter([ ( Schema::field("corporate_name", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdaad::NAME_OF_CORPORATE_BODY), ), ]) } fn work(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap { HashMap::from_iter([ ( Schema::field("title", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdawd::TITLE_OF_WORK), ), ]) } fn expression(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap { HashMap::from_iter([ ( Schema::field("title", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdaed::TITLE_OF_EXPRESSION), ), ]) } fn manifestation(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap { HashMap::from_iter([ ( Schema::field("title", self.language.primary_language()), self.extract_string(graph, subject, vocab::rdamd::TITLE_OF_MANIFESTATION), ), ]) } pub fn graph(&self, graph: &Graph) -> Vec> { let mut entities_and_types = HashSet::new(); let triples = graph.triples_for_predicate(vocab::rdf::TYPE); for triple in triples { if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject && let TermRef::NamedNode(class) = triple.object { entities_and_types.insert((subject, class)); } } entities_and_types.par_iter() .filter_map(|(subject, class)| { Class::try_from_named_node(*class).and_then(|class| { match class { Class::RdfProperty => None, Class::RdfsClass => None, Class::SkosConcept => None, Class::Work => Some(self.work(graph, *subject)), Class::Person => Some(self.person(graph, *subject)), Class::CorporateBody => Some(self.corporate_body(graph, *subject)), Class::Expression => Some(self.expression(graph, *subject)), Class::Manifestation => Some(self.manifestation(graph, *subject)), }.map(|mut document| { document.insert(Schema::discriminant_field(), OwnedValue::from(class as u64)); document.insert(Schema::iri_field(), OwnedValue::Str(subject.as_str().to_string())); let curie = self.curie_helper.abbreviate(None, subject.as_str()) .map(OwnedValue::Str) .unwrap_or(OwnedValue::Null); document.insert(Schema::curie_field(), curie); document }) }) }).collect() } pub fn ontology(&self, entities: HashMap) -> Vec> { let label_field = Schema::field("label", self.language.primary_language()); let definition_field = Schema::field("definition", self.language.primary_language()); entities.iter() .map(|(subject, description)| { let mut document = HashMap::with_capacity(4); let discriminant = description.class .as_ref() .and_then(|node| Class::try_from_named_node(node.as_ref())) .map(|doc_type| doc_type as u64) .map(OwnedValue::U64) .unwrap_or(OwnedValue::Null); document.insert(Schema::discriminant_field(), discriminant); let curie = self.curie_helper.abbreviate(None, subject.as_str()) .map(OwnedValue::Str) .unwrap_or(OwnedValue::Null); document.insert(Schema::curie_field(), curie); let subject = OwnedValue::from(subject.as_str()); document.insert(Schema::iri_field(), subject); let label = description.label.clone() .map(OwnedValue::from) .unwrap_or(OwnedValue::Null); document.insert(label_field, label); let definition = description.description.clone() .map(OwnedValue::from) .unwrap_or(OwnedValue::Null); document.insert(definition_field, definition); document }).collect() } }