Skip to main content

clayers_spec/
namespace.rs

1//! All clayers namespace URIs and prefix mappings.
2
3pub const SPEC: &str = "urn:clayers:spec";
4pub const INDEX: &str = "urn:clayers:index";
5pub const REVISION: &str = "urn:clayers:revision";
6pub const PROSE: &str = "urn:clayers:prose";
7pub const TERMINOLOGY: &str = "urn:clayers:terminology";
8pub const ORGANIZATION: &str = "urn:clayers:organization";
9pub const RELATION: &str = "urn:clayers:relation";
10pub const DECISION: &str = "urn:clayers:decision";
11pub const SOURCE: &str = "urn:clayers:source";
12pub const PLAN: &str = "urn:clayers:plan";
13pub const ARTIFACT: &str = "urn:clayers:artifact";
14pub const LLM: &str = "urn:clayers:llm";
15pub const PYTHON: &str = "urn:clayers:python";
16pub const COMBINED: &str = "urn:clayers:combined";
17
18// External standard namespaces (non-layer, used for XMI/UML model integration)
19pub const XMI: &str = "http://www.omg.org/spec/XMI/20131001";
20pub const UML: &str = "http://www.omg.org/spec/UML/20131001";
21pub const XML: &str = "http://www.w3.org/XML/1998/namespace";
22pub const XSI: &str = "http://www.w3.org/2001/XMLSchema-instance";
23
24/// All 13 layer URN constants (excluding combined).
25pub const ALL_LAYERS: &[&str] = &[
26    SPEC,
27    INDEX,
28    REVISION,
29    PROSE,
30    TERMINOLOGY,
31    ORGANIZATION,
32    RELATION,
33    DECISION,
34    SOURCE,
35    PLAN,
36    ARTIFACT,
37    LLM,
38    PYTHON,
39];
40
41/// Prefix-to-URI mapping for all namespaces (18 total: 13 layers + combined + 4 external).
42pub const PREFIX_MAP: &[(&str, &str)] = &[
43    ("spec", SPEC),
44    ("idx", INDEX),
45    ("rev", REVISION),
46    ("pr", PROSE),
47    ("trm", TERMINOLOGY),
48    ("org", ORGANIZATION),
49    ("rel", RELATION),
50    ("dec", DECISION),
51    ("src", SOURCE),
52    ("pln", PLAN),
53    ("art", ARTIFACT),
54    ("llm", LLM),
55    ("py", PYTHON),
56    ("cmb", COMBINED),
57    ("xmi", XMI),
58    ("uml", UML),
59    ("xml", XML),
60    ("xsi", XSI),
61];
62
63/// Get the prefix for a given namespace URI.
64#[must_use]
65pub fn prefix_for(uri: &str) -> Option<&'static str> {
66    PREFIX_MAP.iter().find(|(_, u)| *u == uri).map(|(p, _)| *p)
67}
68
69/// Get the URI for a given prefix.
70#[must_use]
71pub fn uri_for(prefix: &str) -> Option<&'static str> {
72    PREFIX_MAP
73        .iter()
74        .find(|(p, _)| *p == prefix)
75        .map(|(_, u)| *u)
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81    use std::collections::HashSet;
82
83    #[test]
84    fn all_layer_urns_are_distinct() {
85        let mut seen = HashSet::new();
86        for urn in ALL_LAYERS {
87            assert!(seen.insert(urn), "duplicate URN: {urn}");
88        }
89        // Also check COMBINED is distinct from all layers
90        assert!(!seen.contains(&COMBINED));
91    }
92
93    #[test]
94    fn prefix_map_covers_all_layers_plus_combined() {
95        let map_uris: HashSet<&str> = PREFIX_MAP.iter().map(|(_, u)| *u).collect();
96        for urn in ALL_LAYERS {
97            assert!(map_uris.contains(urn), "prefix map missing {urn}");
98        }
99        assert!(map_uris.contains(COMBINED));
100        assert_eq!(PREFIX_MAP.len(), 18);
101    }
102
103    #[test]
104    fn prefix_for_known_uri() {
105        assert_eq!(prefix_for(SPEC), Some("spec"));
106        assert_eq!(prefix_for(TERMINOLOGY), Some("trm"));
107        assert_eq!(prefix_for(COMBINED), Some("cmb"));
108    }
109
110    #[test]
111    fn uri_for_known_prefix() {
112        assert_eq!(uri_for("spec"), Some(SPEC));
113        assert_eq!(uri_for("trm"), Some(TERMINOLOGY));
114        assert_eq!(uri_for("cmb"), Some(COMBINED));
115    }
116}