///|
pub(all) struct BatchQuality {
total : Int
valid : Int
invalid : Int
warning_resources : Int
duplicate_ids : Int
empty_resources : Int
type_counts : Map[String, Int]
issue_counts : Map[String, Int]
} derive(Debug, Eq, ToJson)
///|
fn batch_count(map : Map[String, Int], key : String) -> Unit {
map[key] = map.get(key).unwrap_or(0) + 1
}
///|
pub fn batch_quality(values : Array[Json]) -> BatchQuality {
let type_counts : Map[String, Int] = Map([])
let issue_counts : Map[String, Int] = Map([])
let identities : Map[String, Int] = Map([])
let mut valid = 0
let mut invalid = 0
let mut warnings = 0
let mut empty = 0
for value in values {
let kind = resource_type(value).unwrap_or("")
if kind == "" {
empty += 1
}
batch_count(type_counts, kind)
let report = validate_resource(value)
if report.issues.any(fn(item) { item.severity == "error" }) {
invalid += 1
} else {
valid += 1
}
if report.issues.any(fn(item) { item.severity == "warning" }) {
warnings += 1
}
for issue_item in report.issues {
batch_count(issue_counts, issue_item.code)
}
match bundle_reference_key(value) {
Some(key) => identities[key] = identities.get(key).unwrap_or(0) + 1
None => ()
}
}
let duplicates = identities
.values()
.fold(init=0, fn(total, count) {
if count > 1 {
total + count - 1
} else {
total
}
})
{
total: values.length(),
valid,
invalid,
warning_resources: warnings,
duplicate_ids: duplicates,
empty_resources: empty,
type_counts,
issue_counts,
}
}
///|
pub fn batch_issue_histogram(values : Array[Json]) -> Map[String, Int] {
batch_quality(values).issue_counts
}
///|
pub fn batch_type_histogram(values : Array[Json]) -> Map[String, Int] {
batch_quality(values).type_counts
}
///|
pub fn batch_is_acceptable(values : Array[Json]) -> Bool {
let quality = batch_quality(values)
quality.invalid == 0 && quality.empty_resources == 0
}
///|
pub fn batch_quality_score(values : Array[Json]) -> Int {
let quality = batch_quality(values)
if quality.total == 0 {
100
} else {
quality.valid * 100 / quality.total
}
}
///|
pub fn validate_batch(values : Array[Json]) -> Array[ValidationReport] {
values.map(fn(value) { validate_resource(value) })
}
///|
pub fn filter_resources_by_kind(
values : Array[Json],
kind : ResourceKind,
) -> Array[Json] {
values.filter(fn(value) { resource_kind(value) == kind })
}
///|
pub fn filter_valid_resources(values : Array[Json]) -> Array[Json] {
values.filter(fn(value) { is_valid(value) })
}
///|
pub fn filter_invalid_resources(values : Array[Json]) -> Array[Json] {
values.filter(fn(value) { !is_valid(value) })
}
///|
pub fn sort_resources_by_id(values : Array[Json]) -> Array[Json] {
let output = values.map(fn(value) { value })
output.sort_by(fn(left, right) {
String::compare(
field_string(left, "id").unwrap_or(""),
field_string(right, "id").unwrap_or(""),
)
})
output
}
///|
pub fn sort_resources_by_type(values : Array[Json]) -> Array[Json] {
let output = values.map(fn(value) { value })
output.sort_by(fn(left, right) {
let type_compare = String::compare(
resource_type(left).unwrap_or(""),
resource_type(right).unwrap_or(""),
)
if type_compare == 0 {
String::compare(
field_string(left, "id").unwrap_or(""),
field_string(right, "id").unwrap_or(""),
)
} else {
type_compare
}
})
output
}
///|
pub fn group_resources_by_type(
values : Array[Json],
) -> Map[String, Array[Json]] {
let grouped : Map[String, Array[Json]] = Map([])
for value in values {
let kind = resource_type(value).unwrap_or("")
match grouped.get(kind) {
None => grouped[kind] = [value]
Some(items) => items.push(value)
}
}
grouped
}
///|
pub fn resource_type_count(values : Array[Json], kind : String) -> Int {
group_resources_by_type(values)
.get(kind)
.map(fn(items) { items.length() })
.unwrap_or(0)
}
///|
pub fn unique_resource_ids(values : Array[Json]) -> Array[String] {
let seen : Map[String, Bool] = Map([])
let output : Array[String] = []
for value in values {
match field_string(value, "id") {
None => ()
Some(id) =>
if !seen.contains(id) {
seen[id] = true
output.push(id)
}
}
}
output
}
///|
pub fn resource_index(values : Array[Json]) -> Map[String, Json] {
let index : Map[String, Json] = Map([])
for value in values {
match bundle_reference_key(value) {
Some(key) => index[key] = value
None => ()
}
}
index
}