ontoenv 0.3.0

Rust library for managing ontologies and their imports in a local environment.
Documentation

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:

  1. Create a temporary directory.
  2. Write two simple ontologies to files in that directory, where one imports the other.
  3. Configure and initialize ontoenv to use this directory.
  4. Compute the dependency closure of one ontology to demonstrate that ontoenv correctly 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;

# fn main() -> anyhow::Result<()> {
// 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 union_graph_result = env.get_union_graph(&closure_ids, 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)?;
# Ok(())
# }