///|
pub enum ProvenanceError {
InvalidStage
StageOutOfOrder
EmptyActor
EmptyDetail
} derive(Debug, Eq)
///|
pub struct ProvenanceEvent {
stage : String
actor : String
detail : String
} derive(Debug, Eq)
///|
pub struct ProvenanceLedger {
report_id : String
entries : Array[ProvenanceEvent]
} derive(Debug, Eq)
///|
pub fn provenance_event(
stage : String,
actor : String,
detail : String,
) -> ProvenanceEvent {
{ stage, actor, detail }
}
///|
pub fn provenance_ledger(report_id : String) -> ProvenanceLedger {
{ report_id, entries: [] }
}
///|
fn provenance_rank(stage : String) -> Int? {
match stage {
"created" => Some(0)
"validated" => Some(1)
"rendered" | "exported" => Some(2)
_ => None
}
}
///|
pub fn ProvenanceLedger::record(
self : ProvenanceLedger,
event : ProvenanceEvent,
) -> Result[ProvenanceLedger, ProvenanceError] {
if event.actor.trim() == "" {
return Err(EmptyActor)
}
if event.detail.trim() == "" {
return Err(EmptyDetail)
}
let rank = provenance_rank(event.stage)
if rank is None {
return Err(InvalidStage)
}
if self.entries.length() == 0 && rank.unwrap() != 0 {
return Err(StageOutOfOrder)
}
if self.entries.length() > 0 {
let previous = provenance_rank(
self.entries[self.entries.length() - 1].stage,
)
if previous is None || rank.unwrap() < previous.unwrap() {
return Err(StageOutOfOrder)
}
}
let entries = self.entries.copy()
entries.push(event)
Ok({ report_id: self.report_id, entries })
}
///|
pub fn ProvenanceLedger::events(
self : ProvenanceLedger,
) -> Array[ProvenanceEvent] {
self.entries.copy()
}
///|
pub fn ProvenanceLedger::is_complete(self : ProvenanceLedger) -> Bool {
let mut validated = false
let mut exported = false
for item in self.entries {
if item.stage == "validated" {
validated = true
}
if item.stage == "rendered" || item.stage == "exported" {
exported = true
}
}
validated && exported
}