use crate::ontology::resolver::OntologyResolver;
use std::path::Path;
#[cfg(feature = "bundled-standards")]
static FOAF_METADATA: crate::ontology::core_bundle::OntologyMetadata =
crate::ontology::core_bundle::OntologyMetadata {
name: "foaf",
namespace: "http://xmlns.com/foaf/0.1/",
size: crate::domain::ontology::standards::FOAF_TTL.len(),
content: crate::domain::ontology::standards::FOAF_TTL.as_bytes(),
};
#[cfg(feature = "bundled-standards")]
static DUBLIN_CORE_METADATA: crate::ontology::core_bundle::OntologyMetadata =
crate::ontology::core_bundle::OntologyMetadata {
name: "dc",
namespace: "http://purl.org/dc/elements/1.1/",
size: crate::domain::ontology::standards::DUBLIN_CORE_TTL.len(),
content: crate::domain::ontology::standards::DUBLIN_CORE_TTL.as_bytes(),
};
#[derive(Debug, Clone, Copy)]
pub struct OntologyLoader;
impl OntologyLoader {
pub fn load_content(uri: &str, base_path: &Path) -> Option<Vec<u8>> {
if let Some(ontology) = crate::ontology::CoreOntologyBundle::by_namespace(uri) {
return Some(ontology.content.to_vec());
}
if let Some(ontology) = crate::ontology::CoreOntologyBundle::by_name(uri) {
return Some(ontology.content.to_vec());
}
#[cfg(feature = "bundled-standards")]
{
if uri == "http://xmlns.com/foaf/0.1/" || uri == "foaf" {
return Some(FOAF_METADATA.content.to_vec());
}
if uri == "http://purl.org/dc/elements/1.1/" || uri == "dc" {
return Some(DUBLIN_CORE_METADATA.content.to_vec());
}
}
let resolved_paths = OntologyResolver::resolve(Path::new(uri), base_path);
for path in resolved_paths {
if path.exists() {
if let Ok(content) = std::fs::read(&path) {
return Some(content);
}
}
}
None
}
pub fn get_metadata(
uri: &str,
) -> Option<&'static crate::ontology::core_bundle::OntologyMetadata> {
if let Some(meta) = crate::ontology::CoreOntologyBundle::by_namespace(uri)
.or_else(|| crate::ontology::CoreOntologyBundle::by_name(uri))
{
return Some(meta);
}
#[cfg(feature = "bundled-standards")]
{
if uri == "http://xmlns.com/foaf/0.1/" || uri == "foaf" {
return Some(&FOAF_METADATA);
}
if uri == "http://purl.org/dc/elements/1.1/" || uri == "dc" {
return Some(&DUBLIN_CORE_METADATA);
}
}
None
}
pub fn is_embedded(uri: &str) -> bool {
if crate::ontology::CoreOntologyBundle::by_namespace(uri).is_some()
|| crate::ontology::CoreOntologyBundle::by_name(uri).is_some()
{
return true;
}
#[cfg(feature = "bundled-standards")]
{
if uri == "http://xmlns.com/foaf/0.1/"
|| uri == "foaf"
|| uri == "http://purl.org/dc/elements/1.1/"
|| uri == "dc"
{
return true;
}
}
false
}
pub fn list_embedded() -> Vec<(&'static str, &'static str)> {
let mut list = crate::ontology::CoreOntologyBundle::available();
#[cfg(feature = "bundled-standards")]
{
list.push(("foaf", "http://xmlns.com/foaf/0.1/"));
list.push(("dc", "http://purl.org/dc/elements/1.1/"));
}
list
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_load_core_ontology() {
let content = OntologyLoader::load_content(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
Path::new("."),
);
assert!(
content.is_some(),
"RDF ontology should be available in core bundle"
);
assert!(
!content.unwrap().is_empty(),
"Ontology content should not be empty"
);
}
#[test]
fn test_is_embedded() {
assert!(OntologyLoader::is_embedded(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#"
));
assert!(OntologyLoader::is_embedded("owl"));
}
#[test]
fn test_get_metadata() {
let meta = OntologyLoader::get_metadata("http://www.w3.org/2002/07/owl#");
assert!(meta.is_some());
if let Some(m) = meta {
assert_eq!(m.name, "owl");
assert!(!m.content.is_empty());
}
}
#[test]
fn test_list_embedded() {
let embedded = OntologyLoader::list_embedded();
assert!(!embedded.is_empty());
for (name, uri) in embedded {
assert!(!name.is_empty(), "Name should not be empty");
assert!(
uri.starts_with("http") || uri.starts_with("https"),
"URI should start with http/https"
);
}
}
#[test]
fn test_nonexistent_ontology() {
let content =
OntologyLoader::load_content("http://example.com/nonexistent#", Path::new("."));
let _ = content; }
#[test]
fn test_is_embedded_for_all_core_ontologies() {
let embedded_list = OntologyLoader::list_embedded();
for (name, uri) in embedded_list {
assert!(
OntologyLoader::is_embedded(uri),
"Ontology {} with URI {} should be embedded",
name,
uri
);
assert!(
OntologyLoader::is_embedded(name),
"Ontology {} should be embedded by name",
name
);
}
}
#[test]
fn test_get_metadata_returns_correct_size() {
let embedded = OntologyLoader::list_embedded();
for (_name, uri) in embedded {
let meta = OntologyLoader::get_metadata(uri);
assert!(meta.is_some(), "Should have metadata for {}", uri);
if let Some(m) = meta {
assert!(m.size > 0, "Size should be non-zero for {}", uri);
assert!(
!m.content.is_empty(),
"Content should not be empty for {}",
uri
);
assert_eq!(m.size, m.content.len(), "Size should match content length");
}
}
}
#[test]
fn test_load_content_returns_bytes() {
let embedded = OntologyLoader::list_embedded();
for (_name, uri) in embedded {
let content = OntologyLoader::load_content(uri, Path::new("."));
assert!(content.is_some(), "Should load content for {}", uri);
assert!(
!content.unwrap().is_empty(),
"Content should not be empty for {}",
uri
);
}
}
#[test]
fn test_metadata_consistency() {
let rdf_uri = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
let metadata = OntologyLoader::get_metadata(rdf_uri);
let content = OntologyLoader::load_content(rdf_uri, Path::new("."));
assert!(metadata.is_some());
assert!(content.is_some());
if let (Some(meta), Some(cnt)) = (metadata, content) {
assert_eq!(
meta.content.len(),
cnt.len(),
"Metadata content length should match loaded content"
);
}
}
#[test]
fn test_nonexistent_uri_returns_none() {
assert!(OntologyLoader::get_metadata("http://example.com/fake#").is_none());
assert!(OntologyLoader::load_content("http://example.com/fake#", Path::new(".")).is_none());
assert!(!OntologyLoader::is_embedded("http://example.com/fake#"));
}
#[test]
fn test_deterministic_hashing() {
let uri = "http://www.w3.org/2002/07/owl#";
let content1 = OntologyLoader::load_content(uri, Path::new("."));
let content2 = OntologyLoader::load_content(uri, Path::new("."));
let content3 = OntologyLoader::load_content(uri, Path::new("."));
assert_eq!(
content1, content2,
"Same URI should return identical content"
);
assert_eq!(
content2, content3,
"Same URI should return identical content"
);
}
#[test]
fn test_fallback_by_name_and_namespace() {
let by_name = OntologyLoader::load_content("owl", Path::new("."));
let by_namespace =
OntologyLoader::load_content("http://www.w3.org/2002/07/owl#", Path::new("."));
assert!(by_name.is_some(), "Should load by short name");
assert!(by_namespace.is_some(), "Should load by full namespace");
}
#[test]
fn test_is_embedded_negative() {
assert!(!OntologyLoader::is_embedded("http://example.com/ontology#"));
assert!(!OntologyLoader::is_embedded("notanontology"));
assert!(!OntologyLoader::is_embedded(""));
assert!(!OntologyLoader::is_embedded(
"HTTP://www.w3.org/1999/02/22-rdf-syntax-ns#"
)); }
#[test]
fn test_list_embedded_no_duplicates() {
let embedded = OntologyLoader::list_embedded();
let mut names = std::collections::HashSet::new();
let mut uris = std::collections::HashSet::new();
for (name, uri) in embedded {
assert!(names.insert(name), "Duplicate name found: {}", name);
assert!(uris.insert(uri), "Duplicate URI found: {}", uri);
}
}
#[test]
fn test_list_embedded_validity() {
let embedded = OntologyLoader::list_embedded();
for (name, uri) in embedded {
assert!(!name.is_empty(), "Name should not be empty");
assert!(!uri.is_empty(), "URI should not be empty");
assert!(uri.starts_with("http"), "URI should start with http");
assert!(
uri.ends_with('#') || uri.ends_with('/'),
"URI should end with # or /"
);
assert!(
OntologyLoader::load_content(uri, Path::new(".")).is_some(),
"Listed ontology {} should be loadable",
name
);
}
}
#[test]
fn test_multiple_lookups_thread_safe() {
for _ in 0..100 {
let _ = OntologyLoader::load_content(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
Path::new("."),
);
let _ = OntologyLoader::get_metadata("http://www.w3.org/2000/01/rdf-schema#");
let _ = OntologyLoader::is_embedded("owl");
}
}
}