99 releases
| new 0.5.5 | May 25, 2026 |
|---|---|
| 0.5.3 | Apr 3, 2026 |
| 0.5.1 | Mar 5, 2026 |
| 0.5.0-a2 | Dec 23, 2025 |
| 0.1.9-a6 | Jul 31, 2024 |
#432 in Web programming
Used in 3 crates
1MB
5.5K
SLoC
ontoenv is an environment manager for ontologies. It can be used as a Rust library to manage local and remote RDF ontologies and their dependencies.
It recursively discovers and resolves owl:imports statements, and provides an API for querying the dependency graph and retrieving a unified "imports closure" of an ontology.
The environment is backed by an Oxigraph store.
Usage
Here is a basic example of how to use the ontoenv Rust library. This example will:
- Create a temporary directory.
- Write two simple ontologies to files in that directory, where one imports the other.
- Configure and initialize
ontoenvto use this directory. - Compute the dependency closure of one ontology to demonstrate that
ontoenvcorrectly resolves and includes the imported ontology.
use ontoenv::config::Config;
use ontoenv::ToUriString;
use ontoenv::api::{OntoEnv, ResolveTarget};
use oxigraph::model::NamedNode;
use std::path::PathBuf;
use std::fs;
use std::io::Write;
use std::collections::HashSet;
// Set up a temporary directory for the example
let test_dir = PathBuf::from("target/doc_test_temp_readme");
if test_dir.exists() {
fs::remove_dir_all(&test_dir)?;
}
fs::create_dir_all(&test_dir)?;
let root = test_dir.canonicalize()?;
// Create a dummy ontology file for ontology A
let ontology_a_path = root.join("ontology_a.ttl");
let mut file_a = fs::File::create(&ontology_a_path)?;
writeln!(file_a, r#"
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix : <http://example.com/ontology_a#> .
<http://example.com/ontology_a> a owl:Ontology .
"#)?;
// Create a dummy ontology file for ontology B which imports A
let ontology_b_path = root.join("ontology_b.ttl");
let mut file_b = fs::File::create(&ontology_b_path)?;
writeln!(file_b, r#"
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix : <http://example.com/ontology_b#> .
<http://example.com/ontology_b> a owl:Ontology ;
owl:imports <http://example.com/ontology_a> .
"#)?;
// Configure ontoenv
let config = Config::builder()
.root(root.clone())
.locations(vec![root.clone()])
.temporary(true) // Use a temporary environment
.build()?;
// Initialize the environment
let mut env = OntoEnv::init(config, false)?;
env.update()?;
// Check that our ontologies were loaded
let ontologies = env.ontologies();
assert_eq!(ontologies.len(), 2);
// Get the dependency closure for ontology B
let ont_b_name = NamedNode::new("http://example.com/ontology_b")?;
let ont_b_id = env.resolve(ResolveTarget::Graph(ont_b_name)).unwrap();
let closure_ids = env.get_closure(&ont_b_id, -1)?;
// The closure should contain both ontology A and B
assert_eq!(closure_ids.len(), 2);
let closure_names: HashSet<String> = closure_ids.iter().map(|id| id.to_uri_string()).collect();
assert!(closure_names.contains("http://example.com/ontology_a"));
assert!(closure_names.contains("http://example.com/ontology_b"));
// We can also get the union graph of the closure
let root = closure_ids[0].name();
let union_graph_result = env.get_union_graph(&closure_ids, root, Some(false), Some(false))?;
// Each ontology has 1 triple, so the union should have 2.
// the 'ontology_a' declaration gets removed by default so that the closure
// only has one ontology declaration.
assert_eq!(union_graph_result.dataset.len(), 2);
// Clean up
fs::remove_dir_all(&test_dir)?;
Dependencies
~44–61MB
~1M SLoC