Skip to main content

owl_structural_model/
ontology.rs

1//! OWL ontology identity values.
2
3use std::fmt::{Display, Formatter};
4
5use iri_rfc3987::Iri;
6
7use crate::StructuralModelError;
8
9const KIND_ONTOLOGY_ID: &str = "ontology ID";
10
11/// OWL ontology identity: optional ontology IRI plus optional version IRI.
12#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
13pub struct OntologyId {
14    ontology_iri: Option<Iri<String>>,
15    version_iri: Option<Iri<String>>,
16}
17
18/// Alias emphasizing that this value is metadata rather than a document.
19pub type OntologyIdentity = OntologyId;
20
21impl OntologyId {
22    /// Create an anonymous ontology ID.
23    #[must_use]
24    pub fn anonymous() -> Self { Self { ontology_iri: None, version_iri: None } }
25
26    /// Create a named ontology ID.
27    #[must_use]
28    pub fn named(ontology_iri: Iri<String>) -> Self {
29        Self { ontology_iri: Some(ontology_iri), version_iri: None }
30    }
31
32    /// Create a versioned ontology ID.
33    #[must_use]
34    pub fn versioned(ontology_iri: Iri<String>, version_iri: Iri<String>) -> Self {
35        Self { ontology_iri: Some(ontology_iri), version_iri: Some(version_iri) }
36    }
37
38    /// Create an ontology ID from optional identity fields.
39    ///
40    /// # Errors
41    ///
42    /// Returns [`StructuralModelError::InvalidFormat`] when a version IRI is
43    /// supplied without an ontology IRI.
44    pub fn try_new(
45        ontology_iri: Option<Iri<String>>,
46        version_iri: Option<Iri<String>>,
47    ) -> Result<Self, StructuralModelError> {
48        if ontology_iri.is_none() && version_iri.is_some() {
49            return Err(StructuralModelError::InvalidFormat {
50                kind: KIND_ONTOLOGY_ID,
51                value: "version-only".to_owned(),
52                message: "version IRI requires ontology IRI",
53            });
54        }
55        Ok(Self { ontology_iri, version_iri })
56    }
57
58    /// Return the ontology IRI when present.
59    #[must_use]
60    pub fn ontology_iri(&self) -> Option<&Iri<String>> { self.ontology_iri.as_ref() }
61
62    /// Return the version IRI when present.
63    #[must_use]
64    pub fn version_iri(&self) -> Option<&Iri<String>> { self.version_iri.as_ref() }
65
66    /// Return whether this ID has no ontology IRI.
67    #[must_use]
68    pub fn is_anonymous(&self) -> bool { self.ontology_iri.is_none() }
69}
70
71impl Display for OntologyId {
72    fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
73        match (&self.ontology_iri, &self.version_iri) {
74            (Some(ontology), Some(version)) => write!(formatter, "{ontology} @ {version}"),
75            (Some(ontology), None) => formatter.write_str(ontology.as_str()),
76            (None, None) => formatter.write_str("anonymous ontology"),
77            (None, Some(_)) => formatter.write_str("invalid version-only ontology ID"),
78        }
79    }
80}