96 lines
3.1 KiB
Rust
96 lines
3.1 KiB
Rust
use super::*;
|
|
|
|
pub(super) fn resettable(_facet: &FacetSelector) -> bool {
|
|
true
|
|
}
|
|
|
|
impl ReviewRow {
|
|
pub(super) fn effective_trace(&self, project: &Project) -> Option<Trace> {
|
|
let mut trace = project.traces.get(&self.trace?)?.clone();
|
|
if let Some(baseline) = trace.baseline.as_mut().and_then(|b| b.semantic.as_mut()) {
|
|
baseline
|
|
.facets
|
|
.retain(|f| !self.resets.contains(&f.selector()));
|
|
}
|
|
Some(trace)
|
|
}
|
|
|
|
pub(super) fn reset_history(
|
|
&mut self,
|
|
project: &Project,
|
|
facet: FacetSelector,
|
|
reset: bool,
|
|
) -> Result<(), String> {
|
|
if !reset && self.resets.remove(&facet) {
|
|
return Ok(());
|
|
}
|
|
let exists = self
|
|
.trace
|
|
.and_then(|id| project.traces.get(&id))
|
|
.and_then(|t| t.baseline.as_ref())
|
|
.and_then(|b| b.semantic.as_ref())
|
|
.is_some_and(|b| b.facets.iter().any(|f| f.selector() == facet));
|
|
if !exists || !resettable(&facet) {
|
|
return Err("Choose an exact existing observation to reset.".into());
|
|
}
|
|
if reset {
|
|
self.resets.insert(facet);
|
|
} else {
|
|
self.resets.remove(&facet);
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
// Only persisted typed addresses establish correspondence. Order vectors and
|
|
// arbitrary scalar values cannot be zipped or searched for UUID-shaped prose.
|
|
pub(super) fn reviewed_pairs(
|
|
row: &ReviewRow,
|
|
project: &Project,
|
|
) -> Result<BTreeMap<Id, Id>, String> {
|
|
let trace = row
|
|
.effective_trace(project)
|
|
.ok_or("Choose an existing trace history.")?;
|
|
let mut result = BTreeMap::new();
|
|
for fact in trace
|
|
.baseline
|
|
.iter()
|
|
.flat_map(|b| b.semantic.iter())
|
|
.flat_map(|b| &b.facets)
|
|
{
|
|
let mut pairs = vec![];
|
|
match fact.selector() {
|
|
FacetSelector::Member { keys, .. }
|
|
| FacetSelector::Binding(keys)
|
|
| FacetSelector::Child(keys)
|
|
| FacetSelector::Incident { keys, .. }
|
|
| FacetSelector::Artifact { keys, .. } => {
|
|
if let (Some(oa), Some(sa)) = (keys.oa, keys.sa) {
|
|
pairs.push((oa, sa));
|
|
}
|
|
}
|
|
FacetSelector::Annotation(KeyPair {
|
|
oa: Some(oa),
|
|
sa: Some(sa),
|
|
}) => {
|
|
if oa.path.len() != sa.path.len() {
|
|
return Err("Historical annotation addresses have different depths; restore their correspondence explicitly.".into());
|
|
}
|
|
pairs.extend(
|
|
oa.path
|
|
.into_iter()
|
|
.chain([oa.field])
|
|
.zip(sa.path.into_iter().chain([sa.field])),
|
|
);
|
|
}
|
|
_ => {}
|
|
}
|
|
for (oa, sa) in pairs {
|
|
if result.insert(oa, sa).is_some_and(|old| old != sa) {
|
|
return Err("Historical observations pair one Operational identity with different System identities. Resolve exact history before restoring pairs.".into());
|
|
}
|
|
}
|
|
}
|
|
Ok(result)
|
|
}
|