Skip to content

Validation across metadata documents #23

@clbarnes

Description

@clbarnes

We currently validate a single metadata document at a time, but some validation requires that specific other Zarr nodes exist and have particular Zarr metadata and OME-Zarr metadata. For now, all such paths are relative and on the same store (but RFC-8 Collections may change this).

An approach:

  • define a trait with a method which traverses an OME-Zarr metadata struct and pulls all the references (as relative paths)
  • users call that method, supply the absolute path of the node they're pulling it from, then use their own object-fetching logic to populate a map of absolute paths to some struct containing Zarr metadata and OME-Zarr metadata
  • supply this map to validatrix::ValidateContext::validate(context), which only implements validation related to the cross-references
pub trait HasReferences {
    fn gather_refs(&self, references: &mut BTreeSet<PathBuf>);
}

impl HasReferences for OmeFields { ... }

impl validatrix::Validate for OmeFields { ... }

impl validatrix::ValidateContext for OmeFields {
    type Context = BTreeMap<(ZarrMetadata, Option<OmeFields>)>;
}

fn get_context_entry(abs_path: impl AsRef<Path>, refs: &mut BTreeSet<PathBuf>) -> Result<(ZarrMetadata, Option<OmeFields>)> {
    let meta = get_zarr_metadata(abs_path.as_ref())?;
    let m_ome: Option<OmeFields> = (&meta).try_into()?;
    if let Some(ref ome) = m_ome {
        ome.validate()?;
        ome.gather_refs(refs);
    }
    Ok((meta, m_ome))
}

fn main() -> Result<()> {
    // somewhat pseudocode-y
    let root_path: PathBuf = "/path/to/node".into();
    let mut ctx = BTreeMap::default();
    let mut refs = BTreeSet::default();
    ctx.insert(root_path.clone(), get_context_entry(&root_path, &mut refs)?);

    while let Some(rel_path) = refs.pop_last() {
        let abs_path = root_path.join(rel_path);
        if ctx.contains_key(&abs_path) {
            continue;
        }
        let val = get_context_entry(&abs_path, &mut refs)?;
        ctx.insert(abs_path, val);
    }

    // could validate the entire graph of interrelated zarr nodes
    for (abs_path, (zarr_meta, m_ome)) in ctx.iter() {
        if let Some(ref ome) = m_ome {
            <OmeFields as ValidateContext>::validate(ome, &ctx)?;
        }
    }
    // or just the one node we actually asked about
    let (zarr_meta, m_ome) = ctx.get(&root_path).unwrap();
    if let Some(ref ome) = m_ome {
        <OmeFields as ValidateContext>::validate(ome, &ctx)?;
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions