local io = io local csv = require "csv" local uuid = require "uuid" -- Random number generator for uuid() local posix_uuid = pcall(function() uuid.set_rng(uuid.rng.urandom()) end) if not posix_uuid then rng = uuid.set_rng(uuid.rng.win_ffi()) end local M = {} -- Submission module -- Adapted from lua-nĂșcleo local function escape_pattern(s) local matches = { ["^"] = "%^"; ["$"] = "%$"; ["("] = "%("; [")"] = "%)"; ["%"] = "%%"; ["."] = "%."; ["["] = "%["; ["]"] = "%]"; ["*"] = "%*"; ["+"] = "%+"; ["-"] = "%-"; ["?"] = "%?"; ["\0"] = "%z"; } return (s:gsub(".", matches)) end M.generate_sip = function(path) local sub_data = assert(csv.open(path)) local md = {} local prev_ref, prev_k -- Collate metadata. local i = 1 for row in sub_data:lines() do ref, k, v = table.unpack(row) -- nil-out empty cells (they come through as "") if ref == "" then ref = nil end if k == "" then k = nil end if v == "" then v = nil end print("Parsing row:", ref, k, v) -- v can be a legit false value. if ref and not k and v == nil then -- This can be a placeholder for ordering purposes. md[ref] = md_ref or {} goto continue elseif v == nil then goto continue else -- If ref or k are missing, reuse the previous one. if ref then prev_ref = ref else if not prev_ref then -- If column 1 is empty, it must have been set in a -- previous row. error(string.format( "Reference in column 1, row %d not found!", i), 2) end ref = prev_ref end if k then prev_k = k else if not prev_k then -- If column 2 is empty, it must have been set in a -- previous row. error(string.format( "Property key in column 2, row %d not found!", i), 2) end k = prev_k end end md[ref] = md[ref] or {id = uuid(), path = ref, _sort = i} md[ref][k] = md[ref][k] or {} if k == "type" then md[ref][k] = v else table.insert(md[ref][k], v) end ::continue:: i = i + 1 end -- Move md to an ordered list. mdlist = {root_path = path:match("(.*/)")} for _, v in pairs(md) do table.insert(mdlist, v) end table.sort(mdlist, function (a, b) return (a._sort < b._sort) end) -- Infer structure from paths and row ordering. for i, v in ipairs(mdlist) do for j = i + 1, #mdlist do --print(string.format("comparing %s : %s", v.path, mdlist[j].path)) if not v["next"] and mdlist[j].path:match("(.*/)") == v.path:match("(.*/)") then --print("next match.") v["next"] = mdlist[j].path end if not v.firstChild and mdlist[j].path:match("^" .. escape_pattern(v.path)) then --print("First child match.") v.firstChild = mdlist[j].path end end v._sort = nil end return mdlist end M.deposit = function(sip) for i, rsrc in ipairs(sip) do print(("Processing resource #%d of %d"):format(i, #sip)) abs_path = sip.root_path end end return M