Files
tools/publish/src/rdf/materialize.rs
T

115 lines
3.8 KiB
Rust
Raw Normal View History

2026-08-05 18:33:30 -04:00
use crate::error;
use gl_graph::vocab::owl;
2026-06-30 19:25:15 -04:00
use oxigraph::model::{Dataset, GraphName, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Term};
use oxigraph::sparql::SparqlEvaluator;
2026-06-23 21:55:52 -04:00
use oxigraph::store::Store;
2026-06-30 19:25:15 -04:00
use tracing::{debug, debug_span};
2026-06-23 21:55:52 -04:00
2026-06-30 19:25:15 -04:00
const INFERENCE_GRAPH: NamedNodeRef = NamedNodeRef::new_unchecked("https://graphofliberty.org/inference");
const RDF_SCHEMA: NamedNodeRef = NamedNodeRef::new_unchecked("http://www.w3.org/2000/01/rdf-schema#");
2026-06-29 15:20:02 -04:00
pub fn same_as(store: &mut Store) -> error::Result<()> {
2026-07-22 20:34:15 -04:00
let _span = debug_span!("Materialize owl:sameAs").entered();
2026-06-30 19:25:15 -04:00
2026-06-23 21:55:52 -04:00
let additional_quads = store
.quads_for_pattern(None, Some(owl::SAME_AS), None, None)
.filter_map(Result::ok)
.fold(Dataset::new(), |mut new_dataset, alias| {
if let NamedOrBlankNode::NamedNode(x) = alias.subject
&& let Term::NamedNode(y) = alias.object
{
for mut quad in store.quads_for_pattern(
Some(NamedOrBlankNodeRef::NamedNode(x.as_ref())),
None,
None,
None,
).filter_map(Result::ok) {
quad.subject = NamedOrBlankNode::NamedNode(y.clone());
2026-06-30 19:25:15 -04:00
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
2026-06-23 21:55:52 -04:00
new_dataset.insert(quad.as_ref());
}
for mut quad in store.quads_for_pattern(
Some(NamedOrBlankNodeRef::NamedNode(y.as_ref())),
None,
None,
None,
).filter_map(Result::ok) {
quad.subject = NamedOrBlankNode::NamedNode(x.clone());
2026-06-30 19:25:15 -04:00
quad.graph_name = GraphName::NamedNode(INFERENCE_GRAPH.into_owned());
2026-06-23 21:55:52 -04:00
new_dataset.insert(quad.as_ref());
}
}
new_dataset
});
let old_size = store.len()?;
store.extend(&additional_quads)?;
let new_size = store.len()?;
if new_size > old_size {
2026-06-30 19:25:15 -04:00
let difference = new_size - old_size;
debug!(?old_size, ?new_size, ?difference, "same_as");
same_as(store)?;
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
Ok(())
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
pub fn super_properties(store: &mut Store) -> error::Result<()> {
2026-07-22 20:34:15 -04:00
let _span = debug_span!("Materialize rdfs:subPropertyOf").entered();
2026-06-23 21:55:52 -04:00
2026-06-30 19:25:15 -04:00
let update = SparqlEvaluator::new()
.with_prefix("rdfs", RDF_SCHEMA.as_str())?
.with_prefix("inference", INFERENCE_GRAPH.as_str())?
.parse_update(r#"INSERT {
GRAPH inference: {
?property rdfs:subPropertyOf ?parent .
?subject ?parent ?object .
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
} WHERE {
GRAPH ?g1 { ?property rdfs:subPropertyOf+ ?parent }
2026-06-30 19:44:27 -04:00
OPTIONAL { GRAPH ?g2 { ?subject ?property ?object } }
2026-06-30 19:25:15 -04:00
}"#)?;
2026-06-23 21:55:52 -04:00
2026-06-29 15:20:02 -04:00
let old_size = store.len()?;
2026-06-30 19:25:15 -04:00
update.on_store(&store).execute()?;
2026-06-29 15:20:02 -04:00
let new_size = store.len()?;
2026-06-23 21:55:52 -04:00
if new_size > old_size {
2026-06-30 19:25:15 -04:00
let difference = new_size - old_size;
debug!(?old_size, ?new_size, ?difference, "super_properties");
super_properties(store)?;
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
Ok(())
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
pub fn super_classes(store: &mut Store) -> error::Result<()> {
2026-07-22 20:34:15 -04:00
let _span = debug_span!("Materialize rdfs:subClassOf").entered();
2026-06-23 21:55:52 -04:00
2026-06-30 19:25:15 -04:00
let update = SparqlEvaluator::new()
.with_prefix("rdfs", RDF_SCHEMA.as_str())?
.with_prefix("inference", INFERENCE_GRAPH.as_str())?
.parse_update(r#"INSERT {
GRAPH inference: {
?class rdfs:subClassOf ?parent .
?item a ?parent .
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
} WHERE {
2026-06-30 19:35:47 -04:00
GRAPH ?g1 { ?class rdfs:subClassOf+ ?parent }
OPTIONAL { GRAPH ?g2 { ?item a ?class } }
2026-06-30 19:25:15 -04:00
}"#)?;
2026-06-23 21:55:52 -04:00
2026-06-30 19:25:15 -04:00
let old_size = store.len()?;
update.on_store(&store).execute()?;
let new_size = store.len()?;
2026-06-23 21:55:52 -04:00
2026-06-30 19:25:15 -04:00
if new_size > old_size {
let difference = new_size - old_size;
debug!(?old_size, ?new_size, ?difference, "super_classes");
super_classes(store)?;
2026-06-23 21:55:52 -04:00
}
2026-06-30 19:25:15 -04:00
Ok(())
}