morphir_core/metadata/
assertion.rs1use super::{Fact, MetadataError};
4use crate::node_address::NodeUri;
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
11pub struct DocumentId(String);
12
13impl DocumentId {
14 pub fn new(id: impl Into<String>) -> Result<Self, MetadataError> {
16 let id = id.into();
17 if id.is_empty() {
18 Err(MetadataError::EmptyDocumentId)
19 } else {
20 Ok(Self(id))
21 }
22 }
23
24 pub fn as_str(&self) -> &str {
26 &self.0
27 }
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
32pub enum Carrier {
33 AttributesFacts(NodeUri),
35 AnnotationsFacts(NodeUri),
37 DocumentGraph,
39 Sidecar {
41 target: NodeUri,
43 entry_point: NodeUri,
45 },
46}
47
48impl Carrier {
49 fn identity(&self) -> String {
50 match self {
51 Self::AttributesFacts(uri) => serde_json::to_string(&("attributes", uri.to_string())),
52 Self::AnnotationsFacts(uri) => serde_json::to_string(&("annotations", uri.to_string())),
53 Self::DocumentGraph => serde_json::to_string(&("documentGraph",)),
54 Self::Sidecar {
55 target,
56 entry_point,
57 } => serde_json::to_string(&("sidecar", target.to_string(), entry_point.to_string())),
58 }
59 .expect("carrier identities serialize")
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct AssertionKey {
66 owner: DocumentId,
67 carrier: Carrier,
68 fact: Fact,
69}
70
71impl AssertionKey {
72 pub fn new(owner: DocumentId, carrier: Carrier, fact: Fact) -> Result<Self, MetadataError> {
77 match &carrier {
78 Carrier::AttributesFacts(uri) | Carrier::AnnotationsFacts(uri)
79 if uri != fact.subject() =>
80 {
81 Err(MetadataError::CarrierSubjectMismatch)
82 }
83 Carrier::Sidecar { target, .. } if target != fact.subject() => {
84 Err(MetadataError::CarrierSubjectMismatch)
85 }
86 _ => Ok(Self {
87 owner,
88 carrier,
89 fact,
90 }),
91 }
92 }
93
94 pub fn owner(&self) -> &DocumentId {
96 &self.owner
97 }
98
99 pub fn carrier(&self) -> &Carrier {
101 &self.carrier
102 }
103
104 pub fn fact(&self) -> &Fact {
106 &self.fact
107 }
108
109 pub(crate) fn identity(&self) -> String {
110 serde_json::to_string(&(
111 self.owner.as_str(),
112 self.carrier.identity(),
113 self.fact.identity(),
114 ))
115 .expect("assertion identities serialize")
116 }
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
121pub enum AssertionSource {
122 Document(DocumentId),
124 Compiler {
126 producer: String,
128 reference: Option<String>,
130 },
131 Author {
133 reference: String,
135 },
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
140pub struct Assertion {
141 key: AssertionKey,
142 source_override: Option<Vec<AssertionSource>>,
143}
144
145impl Assertion {
146 pub fn new(key: AssertionKey) -> Self {
148 Self {
149 key,
150 source_override: None,
151 }
152 }
153
154 pub fn key(&self) -> &AssertionKey {
156 &self.key
157 }
158
159 pub fn detail(&self) -> Vec<&AssertionSource> {
161 self.source_override
162 .iter()
163 .flatten()
164 .filter(|source| !matches!(source, AssertionSource::Document(_)))
165 .collect()
166 }
167
168 pub fn source_override(&self) -> Option<&[AssertionSource]> {
170 self.source_override.as_deref()
171 }
172
173 pub fn add_detail(&mut self, source: AssertionSource) -> Result<(), MetadataError> {
176 if matches!(source, AssertionSource::Document(_)) {
177 return Err(MetadataError::DocumentProvenanceIsImplicit);
178 }
179 let mut sources = self.sources();
180 sources.push(source);
181 self.set_source_override(sources)?;
182 Ok(())
183 }
184
185 pub fn sources(&self) -> Vec<AssertionSource> {
187 self.source_override
188 .clone()
189 .unwrap_or_else(|| vec![AssertionSource::Document(self.key.owner.clone())])
190 }
191
192 pub(crate) fn set_source_override(
193 &mut self,
194 mut sources: Vec<AssertionSource>,
195 ) -> Result<(), MetadataError> {
196 if sources.is_empty() {
197 return Err(MetadataError::EmptyAssertionSources);
198 }
199 if sources.iter().any(|source| {
200 matches!(source, AssertionSource::Document(owner) if owner != self.key.owner())
201 }) {
202 return Err(MetadataError::DocumentSourceOwnerMismatch);
203 }
204 sources.sort();
205 sources.dedup();
206 self.source_override = Some(sources);
207 Ok(())
208 }
209
210 pub(crate) fn merge_sources(&mut self, other: &Self) -> Result<(), MetadataError> {
211 if self.source_override.is_some() != other.source_override.is_some() {
212 return Err(MetadataError::SourceKnowledgeConflict(Box::new(
213 self.key.clone(),
214 )));
215 }
216 if let Some(sources) = &other.source_override {
217 let mut merged = self.source_override.clone().unwrap_or_default();
218 merged.extend(sources.iter().cloned());
219 self.set_source_override(merged)?;
220 }
221 Ok(())
222 }
223
224 pub(crate) fn with_key(mut self, key: AssertionKey) -> Self {
225 self.key = key;
226 self
227 }
228}
229
230#[derive(Debug, Clone, PartialEq, Eq)]
258pub struct SourceRecord {
259 selector: AssertionKey,
260 sources: Vec<AssertionSource>,
261}
262
263impl SourceRecord {
264 pub fn new(
266 selector: AssertionKey,
267 sources: Vec<AssertionSource>,
268 ) -> Result<Self, MetadataError> {
269 let mut assertion = Assertion::new(selector.clone());
270 assertion.set_source_override(sources)?;
271 Ok(Self {
272 selector,
273 sources: assertion.sources(),
274 })
275 }
276
277 pub fn selector(&self) -> &AssertionKey {
279 &self.selector
280 }
281
282 pub fn sources(&self) -> &[AssertionSource] {
284 &self.sources
285 }
286}