This commit is contained in:
Alex Wied
2026-06-29 15:20:02 -04:00
parent ee5deb87c1
commit 59c8dffb01
10 changed files with 149 additions and 141 deletions
+51 -52
View File
@@ -9,7 +9,8 @@ use std::fmt::Display;
use std::path::{Path, PathBuf};
use std::sync::LazyLock;
use oxigraph::store::Store;
use crate::rdf::materialize;
use tracing::{info, instrument};
use crate::rdf::{conversion, materialize};
static PREFIXES: LazyLock<BTreeMap<String, String>> = LazyLock::new(|| {
BTreeMap::from_iter([
@@ -57,7 +58,7 @@ impl OntologyBuilder {
}
pub fn build(self) -> error::Result<Ontology> {
let store = if let Some(path) = self.path {
let mut store = if let Some(path) = self.path {
Store::open(path)
} else {
Store::new()
@@ -68,41 +69,40 @@ impl OntologyBuilder {
.map(|(k, v)| (k.to_string(), v.to_string()))
.collect::<HashMap<String, String>>();
let store = materialize::same_as(store)?;
//materialize::super_classes(&mut dataset);
materialize::same_as(&mut store)?;
materialize::super_classes(&mut store)?;
store.optimize()?;
// Full-text search index field names
//let fields = Self::fields(&dataset);
let fields = Self::fields(&store)?;
/*let mut entities: HashMap<NamedNode, Entity> = HashMap::new();
let entity_iris = Self::subclass_of(&dataset, gl::ENTITY)
.chain(Self::subclass_of(&dataset, rda::ENTITY))
.chain([
rdf::PROPERTY.into_owned(),
rdfs::CLASS.into_owned(),
]);
for iri in entity_iris {
let subject = iri.as_ref().into();
let label = dataset.quads_for_pattern(Some(subject), Some(rdfs::LABEL), None, None)
.filter_map(|quad| term_to_string(&quad.object.into_owned()).map(String::from))
let mut entities: HashMap<NamedNode, Entity> = HashMap::new();
// All Entities have exactly one catalog ID.
for quad in store.quads_for_pattern(None, Some(gl::CATALOG_ID), None, None)
.filter_map(Result::ok) {
let label = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::LABEL), None, None)
.filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from))
.next();
let catalog_id = dataset.quads_for_pattern(Some(subject), Some(gl::CATALOG_ID), None, None)
.filter_map(|quad| term_to_u64(&quad.object.into_owned()))
let comment = store.quads_for_pattern(Some(quad.subject.as_ref().into()), Some(rdfs::COMMENT), None, None)
.filter_map(Result::ok)
.filter_map(|quad| conversion::term_to_string(&quad.object).map(String::from))
.next();
if let Some(catalog_id) = catalog_id {
if let Some(catalog_id) = conversion::term_to_u64(&quad.object) &&
let NamedOrBlankNode::NamedNode(subject) = quad.subject &&
let Some(label) = label {
let mut properties = HashSet::new();
for quad in dataset.quads_for_pattern(Some(subject), Some(gl::ASSOCIATED_PROPERTY), None, None) {
if let NamedOrBlankNodeRef::NamedNode(subject) = quad.subject
&& let TermRef::NamedNode(property) = quad.object {
properties.insert(property.into_owned());
for quad in store.quads_for_pattern(Some(subject.as_ref().into()), Some(gl::ASSOCIATED_PROPERTY), None, None)
.filter_map(Result::ok) {
if let Term::NamedNode(property) = quad.object {
properties.insert(property);
}
}
entities.insert(iri, Entity {
label: label.unwrap_or(catalog_id.to_string()),
entities.insert(subject, Entity {
label,
comment,
catalog_id,
properties,
});
@@ -110,28 +110,25 @@ impl OntologyBuilder {
}
let mut indexed_by = HashMap::new();
for quad in dataset.quads_for_pattern(None, Some(gl::INDEXED_BY_FIELD), None, None) {
if let NamedOrBlankNodeRef::NamedNode(subject) = quad.subject
&& let TermRef::NamedNode(field) = quad.object
for quad in store.quads_for_pattern(None, Some(gl::INDEXED_BY_FIELD), None, None)
.filter_map(Result::ok) {
if let NamedOrBlankNode::NamedNode(subject) = quad.subject
&& let Term::NamedNode(field) = quad.object
{
indexed_by.insert(subject.into_owned(), field.into_owned());
indexed_by.insert(subject, field);
}
}*/
}
Ok(Ontology {
store,
prefixes,
fields: HashMap::new(),
entities: HashMap::from_iter([(rdf::PROPERTY.into_owned(), Entity {
label: "property".to_string(),
catalog_id: 0,
properties: HashSet::new(),
})]),
indexed_by: HashMap::new(),
fields,
entities,
indexed_by,
})
}
/*fn fields(dataset: &Dataset) -> HashMap<NamedNode, IndexField> {
fn fields(store: &Store) -> error::Result<HashMap<NamedNode, IndexField>> {
let query = SparqlEvaluator::new()
.parse_query(
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
@@ -147,13 +144,12 @@ SELECT DISTINCT ?subject ?name ?label {
.expect("Unable to parse field query");
let mut results = HashMap::new();
if let QueryResults::Solutions(solutions) =
query.on_queryable_dataset(dataset).execute().unwrap()
if let QueryResults::Solutions(solutions) = query.on_store(store).execute()?
{
for solution in solutions.filter_map(Result::ok) {
let subject = solution.get("subject").and_then(term_to_named_node);
let name = solution.get("name").and_then(term_to_string);
let label = solution.get("label").and_then(term_to_string);
let subject = solution.get("subject").and_then(conversion::term_to_named_node);
let name = solution.get("name").and_then(conversion::term_to_string);
let label = solution.get("label").and_then(conversion::term_to_string);
if let Some(subject) = subject && let Some(name) = name {
let field = IndexField {
@@ -164,10 +160,10 @@ SELECT DISTINCT ?subject ?name ?label {
}
}
}
results
Ok(results)
}
fn subclass_of(dataset: &Dataset, class: NamedNodeRef<'_>) -> impl Iterator<Item = NamedNode> {
/*fn subclass_of(dataset: &Dataset, class: NamedNodeRef<'_>) -> impl Iterator<Item = NamedNode> {
let query = SparqlEvaluator::new()
.parse_query(
format!(
@@ -200,6 +196,7 @@ SELECT ?class {{
pub struct LabeledIri {
pub iri: NamedNode,
pub label: String,
pub comment: Option<String>,
}
impl PartialEq for LabeledIri {
@@ -225,6 +222,7 @@ pub struct IriInformation {
#[derive(Clone, Debug)]
pub struct Entity {
pub label: String,
pub comment: Option<String>,
pub catalog_id: u64,
pub properties: HashSet<NamedNode>,
}
@@ -263,11 +261,6 @@ impl Ontology {
&*PREFIXES
}
/*pub fn info(&self, node: NamedNodeRef<'_>) -> Option<&IriInformation> {
let node = node.into_owned();
self.iri_info.get(&node)
}*/
pub fn abbreviate(&self, node: NamedNodeRef<'_>) -> String {
for (prefix_name, prefix_iri) in &self.prefixes {
if let Some(local_name) = node.as_str().strip_prefix(prefix_iri) {
@@ -314,6 +307,7 @@ impl Ontology {
.map(|entity| LabeledIri {
iri: class.to_owned(),
label: entity.label.to_owned(),
comment: entity.comment.to_owned(),
})
}
@@ -322,9 +316,14 @@ impl Ontology {
.map(|(iri, entity)| LabeledIri {
iri: iri.to_owned(),
label: entity.label.to_owned(),
comment: entity.comment.to_owned(),
})
}
pub fn entities(&self) -> impl Iterator<Item = (&NamedNode, &Entity)> {
self.entities.iter()
}
pub fn datatypes(&self) -> impl Iterator<Item = NamedNode> {
self.store
.quads_for_pattern(