2026-06-23 21:55:52 -04:00
|
|
|
use oxigraph::model::{Dataset, GraphName, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term};
|
|
|
|
|
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
|
|
|
|
use oxigraph::store::Store;
|
|
|
|
|
use crate::error;
|
|
|
|
|
use crate::rdf::vocab::owl;
|
|
|
|
|
|
2026-06-29 15:20:02 -04:00
|
|
|
pub fn same_as(store: &mut Store) -> error::Result<()> {
|
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());
|
|
|
|
|
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());
|
|
|
|
|
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 {
|
|
|
|
|
same_as(store)
|
|
|
|
|
} else {
|
2026-06-29 15:20:02 -04:00
|
|
|
Ok(())
|
2026-06-23 21:55:52 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 15:20:02 -04:00
|
|
|
pub fn super_classes(store: &mut Store) -> error::Result<()> {
|
2026-06-23 21:55:52 -04:00
|
|
|
let query = SparqlEvaluator::new()
|
|
|
|
|
.parse_query(
|
|
|
|
|
r#"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
|
|
|
|
|
|
|
|
CONSTRUCT {
|
|
|
|
|
?item a ?parent
|
|
|
|
|
} WHERE {
|
|
|
|
|
?item a ?class .
|
|
|
|
|
?class rdfs:subClassOf ?parent .
|
|
|
|
|
}"#,
|
|
|
|
|
)
|
|
|
|
|
.expect("Unable to parse superclass query");
|
|
|
|
|
|
|
|
|
|
let mut additional_quads = Dataset::new();
|
2026-06-29 15:20:02 -04:00
|
|
|
if let QueryResults::Graph(graph) = query.on_store(&store).execute().unwrap()
|
2026-06-23 21:55:52 -04:00
|
|
|
{
|
|
|
|
|
additional_quads.extend(graph.filter_map(Result::ok).map(|triple| {
|
|
|
|
|
Quad::new(
|
|
|
|
|
triple.subject,
|
|
|
|
|
triple.predicate,
|
|
|
|
|
triple.object,
|
|
|
|
|
GraphName::DefaultGraph,
|
|
|
|
|
)
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-29 15:20:02 -04:00
|
|
|
let old_size = store.len()?;
|
|
|
|
|
store.extend(&additional_quads)?;
|
|
|
|
|
let new_size = store.len()?;
|
2026-06-23 21:55:52 -04:00
|
|
|
|
|
|
|
|
if new_size > old_size {
|
2026-06-29 15:20:02 -04:00
|
|
|
super_classes(store)
|
|
|
|
|
} else {
|
|
|
|
|
Ok(())
|
2026-06-23 21:55:52 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*fn iri_information(dataset: &Dataset) -> HashMap<NamedNode, IriInformation> {
|
|
|
|
|
let query = SparqlEvaluator::new()
|
|
|
|
|
.parse_query(
|
|
|
|
|
r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
|
|
|
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
|
|
|
PREFIX gl: <https://graphofliberty.org/2026/04/ont/>
|
|
|
|
|
|
|
|
|
|
SELECT DISTINCT ?class ?subject ?label ?comment ?read_only {
|
|
|
|
|
VALUES ?class { rdf:Property rdfs:Class }
|
|
|
|
|
?subject a ?class .
|
|
|
|
|
OPTIONAL {
|
|
|
|
|
?subject rdfs:label ?label
|
|
|
|
|
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?label))
|
|
|
|
|
}
|
|
|
|
|
OPTIONAL {
|
|
|
|
|
?subject rdfs:comment ?comment
|
|
|
|
|
FILTER (langMATCHES(LANG(?label), "en") || !hasLANG(?comment))
|
|
|
|
|
}
|
|
|
|
|
OPTIONAL { ?subject gl:readOnly ?read_only }
|
|
|
|
|
}"#,
|
|
|
|
|
)
|
|
|
|
|
.expect("Unable to parse property query");
|
|
|
|
|
|
|
|
|
|
let mut results = HashMap::new();
|
|
|
|
|
if let QueryResults::Solutions(solutions) =
|
|
|
|
|
query.on_queryable_dataset(dataset).execute().unwrap()
|
|
|
|
|
{
|
|
|
|
|
for solution in solutions.filter_map(Result::ok) {
|
|
|
|
|
let type_ = solution.get("class").and_then(crate::rdf::ontology::term_to_named_node);
|
|
|
|
|
let subject = solution.get("subject").and_then(crate::rdf::ontology::term_to_named_node);
|
|
|
|
|
let label = solution.get("label").and_then(crate::rdf::ontology::term_to_string);
|
|
|
|
|
let comment = solution.get("comment").and_then(crate::rdf::ontology::term_to_string);
|
|
|
|
|
let read_only = solution
|
|
|
|
|
.get("read_only")
|
|
|
|
|
.and_then(crate::rdf::ontology::term_to_boolean)
|
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
|
|
|
|
if let Some(subject) = subject && let Some(type_) = type_ {
|
|
|
|
|
let info = IriInformation {
|
|
|
|
|
type_: type_.clone(),
|
|
|
|
|
label: label.map(String::from),
|
|
|
|
|
comment: comment.map(String::from),
|
|
|
|
|
read_only,
|
|
|
|
|
};
|
|
|
|
|
results.insert(subject.to_owned(), info);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
results
|
|
|
|
|
}*/
|