///|
pub fn ChemReport::validate(self : ChemReport) -> Array[ValidationIssue] {
  let issues : Array[ValidationIssue] = []
  if self.metadata.title.trim().length() == 0 {
    issues.push({ path: "metadata.title", message: "title must not be empty" })
  }
  if self.metadata.process_unit.trim().length() == 0 {
    issues.push({
      path: "metadata.process_unit",
      message: "process unit must not be empty",
    })
  }
  if self.summary.trim().length() == 0 {
    issues.push({ path: "summary", message: "summary must not be empty" })
  }
  if self.results.length() == 0 {
    issues.push({ path: "results", message: "at least one result is required" })
  }
  if self.sources.length() == 0 {
    issues.push({
      path: "sources",
      message: "at least one data source is required",
    })
  }
  for index, result in self.results {
    if result.name.trim().length() == 0 {
      issues.push({
        path: "results[\{index}].name",
        message: "result name must not be empty",
      })
    }
    if result.value.trim().length() == 0 {
      issues.push({
        path: "results[\{index}].value",
        message: "result value must not be empty",
      })
    }
  }
  for index, source in self.sources {
    if source.label.trim().length() == 0 {
      issues.push({
        path: "sources[\{index}].label",
        message: "source label must not be empty",
      })
    }
  }
  issues
}

///|
pub fn ChemReport::is_publish_ready(self : ChemReport) -> Bool {
  self.validate().length() == 0
}