Skip to main content

mif_core/
ontology.rs

1use serde::{Deserialize, Serialize};
2
3/// A reference to the ontology a MIF memory conforms to.
4///
5/// Corresponds to `$defs.OntologyReference` in `mif.schema.json`. `id` must
6/// match the `ontology.id` declared in the referenced ontology definition
7/// (see the three-tier resolution chain: `mif-base` -> `shared-traits` ->
8/// domain ontologies, driven by each ontology's own `extends` list).
9#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
10pub struct OntologyReference {
11    /// JSON-LD type marker. Always `"OntologyReference"` when present;
12    /// preserved verbatim across round-trips rather than re-derived, since
13    /// the schema declares it optional.
14    #[serde(rename = "@type", skip_serializing_if = "Option::is_none")]
15    pub r#type: Option<String>,
16    /// Ontology identifier (`^[a-z][a-z0-9-]*$`).
17    pub id: String,
18    /// Ontology version (`^\d+\.\d+\.\d+.*$`).
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub version: Option<String>,
21    /// URI to the ontology definition.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub uri: Option<String>,
24}
25
26impl OntologyReference {
27    /// Creates a new reference to the ontology identified by `id`.
28    #[must_use]
29    pub const fn new(id: String) -> Self {
30        Self {
31            r#type: None,
32            id,
33            version: None,
34            uri: None,
35        }
36    }
37
38    /// Sets the ontology version.
39    #[must_use]
40    pub fn with_version(mut self, version: String) -> Self {
41        self.version = Some(version);
42        self
43    }
44
45    /// Sets the URI to the ontology definition.
46    #[must_use]
47    pub fn with_uri(mut self, uri: String) -> Self {
48        self.uri = Some(uri);
49        self
50    }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::OntologyReference;
56
57    #[test]
58    fn round_trips_through_json() {
59        let reference = OntologyReference::new("grazing-plan".to_string())
60            .with_version("1.0.0".to_string())
61            .with_uri("https://mif-spec.dev/ontologies/grazing-plan".to_string());
62        let json = serde_json::to_string(&reference).unwrap();
63        let parsed: OntologyReference = serde_json::from_str(&json).unwrap();
64        assert_eq!(reference, parsed);
65    }
66
67    #[test]
68    fn omits_absent_optional_fields() {
69        let reference = OntologyReference::new("mif-base".to_string());
70        let json = serde_json::to_value(&reference).unwrap();
71        assert!(json.get("version").is_none());
72        assert!(json.get("uri").is_none());
73        assert!(json.get("@type").is_none());
74    }
75}