use std::sync::Arc;
use crate::{
Href,
property::Property,
sync::{
analysis::{ItemWithData, ResolvedMapping},
operation::{
ItemOp, MappingUidSource, PropertyOp, PropertyOpKind, StatusWrite, StorageWrite,
WriteItem,
},
status::{MappingUid, Side, StatusVersions},
},
};
pub use super::plan::resolve_conflicts;
#[derive(PartialEq, Debug, Clone)]
pub struct ConflictInfo {
pub a: ItemWithData,
pub b: ItemWithData,
pub old: Option<StatusVersions>,
pub collection_a: Href,
pub collection_b: Href,
}
pub trait ConflictResolver: Send + Sync {
fn resolve_item(&self, conflict: ConflictInfo, mapping_uid: MappingUid) -> ItemOp;
fn resolve_property(
&self,
property: Property,
value_a: String,
value_b: String,
mapping: Arc<ResolvedMapping>,
mapping_uid: MappingUid,
) -> PropertyOp;
}
#[derive(Debug, Clone, Copy)]
pub struct KeepSideResolver(pub Side);
impl ConflictResolver for KeepSideResolver {
fn resolve_item(&self, conflict: ConflictInfo, mapping_uid: MappingUid) -> ItemOp {
let (source, target_version, target_side) = match self.0 {
Side::A => (conflict.a, conflict.b.state.version, Side::B),
Side::B => (conflict.b, conflict.a.state.version, Side::A),
};
let (storage_write, status_write) = match conflict.old {
Some(old) => (
StorageWrite::Update {
target: old.for_side(target_side).clone(),
},
StatusWrite::Update { old },
),
None => (
StorageWrite::Update {
target: target_version,
},
StatusWrite::Insert,
),
};
ItemOp::Write(WriteItem {
source: source.into(),
target_side,
storage_write,
status_write,
mapping_uid: MappingUidSource::Immediate(mapping_uid),
on_complete: None,
})
}
fn resolve_property(
&self,
property: Property,
value_a: String,
value_b: String,
mapping: Arc<ResolvedMapping>,
mapping_uid: MappingUid,
) -> PropertyOp {
let (value, side) = match self.0 {
Side::A => (value_a, Side::B),
Side::B => (value_b, Side::A),
};
PropertyOp {
property,
mapping,
mapping_uid: MappingUidSource::Immediate(mapping_uid),
on_complete: None,
kind: PropertyOpKind::Write { value, side },
}
}
}