123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- local pp = require "pl.pretty"
- local term = require "volksdata.term"
- local pkar = require "pocket_archive"
- local model = require "pocket_archive.model"
- local logger = pkar.logger
- local dbg = require "debugger"
- local E_TYPE = "Type error"
- local E_CARD = "Cardinality error"
- local E_RANGE = "Range error"
- local M = {}
- M.validate = function(gr, s)
- ctype = gr:attr(s, model.id_to_uri.content_type):iter()() or NT
- local rmod = model.from_uri(ctype)
- if not rmod then error("No type definition for " .. ctype.data) end
- local report = {
- id = s.data, ctype = ctype.data,
- notices = {}, warnings = {}, errors = {}
- }
- for fname, rules in pairs(rmod.properties or NT) do
- local values
- values = gr:attr(s, model.id_to_uri[fname])
- -- Cardinality
- if rules.min_cardinality or rules.max_cardinality then
- min_card = rules.min_cardinality or 0
- if #values < min_card then
- table.insert(report.errors, {
- E_CARD,
- ("Too few values for %s: expected %d, got %d"):format(
- fname, min_card, #values)
- })
- end
- max_card = rules.max_cardinality or math.huge
- if #values > max_card then
- table.insert(report.errors, {
- E_CARD,
- ("Too many values for %s: expected %d, got %d"):format(
- fname, max_card, #values)
- })
- end
- end
- -- From this point on, if there are no values, skip other criteria.
- if #values == 0 then goto skip_prop end
- -- Type
- if rules.type then
- -- String type accepts any value.
- if rules.type == "number" then
- for v in pairs(values) do
- if type(v) ~= "number" then
- table.insert(
- report.errors, {
- E_TYPE,
- ("Number expected for %s; got: %s")
- :format(fname, v)
- })
- end
- end
- elseif rules.type == "resource" then
- for _, v in ipairs(values) do
- if v:sub(1,4) ~= "par" then
- table.insert(
- report.errors, {
- E_TYPE,
- ("`par:` prefix expected for %s; got: %s")
- :format(fname, v)
- })
- end
- end
- end
- end
- -- Range
- if rules.range then
- for _, v in ipairs(values) do
- end
- end
- ::skip_prop::
- end
- if #report.errors > 0 then report.max_level = "ERROR"
- elseif #report.warnings > 0 then report.max_level = "WARN"
- elseif #report.notices > 0 then report.max_level = "NOTICE" end
- return report
- end
- return M
|