use std::fmt::{Display, Formatter};
use iri_rfc3987::Iri;
use crate::StructuralModelError;
const KIND_ONTOLOGY_ID: &str = "ontology ID";
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(try_from = "OntologyIdInput")]
pub struct OntologyId {
ontology_iri: Option<Iri<String>>,
version_iri: Option<Iri<String>>,
}
pub type OntologyIdentity = OntologyId;
impl OntologyId {
#[must_use]
pub fn anonymous() -> Self {
Self {
ontology_iri: None,
version_iri: None,
}
}
#[must_use]
pub fn named(ontology_iri: Iri<String>) -> Self {
Self {
ontology_iri: Some(ontology_iri),
version_iri: None,
}
}
#[must_use]
pub fn versioned(ontology_iri: Iri<String>, version_iri: Iri<String>) -> Self {
Self {
ontology_iri: Some(ontology_iri),
version_iri: Some(version_iri),
}
}
pub fn try_new(
ontology_iri: Option<Iri<String>>,
version_iri: Option<Iri<String>>,
) -> Result<Self, StructuralModelError> {
if ontology_iri.is_none() && version_iri.is_some() {
return Err(StructuralModelError::InvalidFormat {
kind: KIND_ONTOLOGY_ID,
value: "version-only".to_owned(),
message: "version IRI requires ontology IRI",
});
}
Ok(Self {
ontology_iri,
version_iri,
})
}
#[must_use]
pub fn ontology_iri(&self) -> Option<&Iri<String>> {
self.ontology_iri.as_ref()
}
#[must_use]
pub fn version_iri(&self) -> Option<&Iri<String>> {
self.version_iri.as_ref()
}
#[must_use]
pub fn is_anonymous(&self) -> bool {
self.ontology_iri.is_none()
}
}
impl Display for OntologyId {
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
match (&self.ontology_iri, &self.version_iri) {
(Some(ontology), Some(version)) => write!(formatter, "{ontology} @ {version}"),
(Some(ontology), None) => formatter.write_str(ontology.as_str()),
(None, None) => formatter.write_str("anonymous ontology"),
(None, Some(_)) => formatter.write_str("invalid version-only ontology ID"),
}
}
}
#[derive(serde::Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename = "OntologyId")]
struct OntologyIdInput {
ontology_iri: Option<Iri<String>>,
version_iri: Option<Iri<String>>,
}
impl TryFrom<OntologyIdInput> for OntologyId {
type Error = StructuralModelError;
fn try_from(input: OntologyIdInput) -> Result<Self, Self::Error> {
Self::try_new(input.ontology_iri, input.version_iri)
}
}