123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- 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 = next(gr:attr(s, pkar.CONTENT_TYPE_P))
- local rmod = model.parse_model(ctype.data)
- if not rmod then error("No type definition for ", ctype.data) end
- local report = {notices = {}, warnings = {}, errors = {}}
- for fname, rules in pairs(rmod.properties or NT) do
- local values
- values = gr:attr(s, term.new_iriref_ns(fname))
- -- Cardinality
- local card = 0
- for _, v in pairs(values) do card = card + 1 end
- if rules.min_cardinality or rules.max_cardinality then
- min_card = rules.min_cardinality or 0
- if card < min_card then
- table.insert(report.errors, {
- E_CARD,
- ("Too few values for %s: expected %d, got %d"):format(
- fname, min_card, card)
- })
- end
- max_card = rules.max_cardinality or math.huge
- if card > max_card then
- table.insert(report.errors, {
- E_CARD,
- ("Too many values for %s: expected %d, got %d"):format(
- fname, max_card, card)
- })
- end
- end
- -- From this point on, if there are no values, skip other criteria.
- if card == 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
|