Die Dokumentation für dieses Modul kann unter Modul:Data/Doku erstellt werden

local p = {}

function p.importData(frame)
	function listFields(sBase, iRecord)
		if not sBase then
			return nil
		end
		local b, vT = pcall(mw.ext.data.get, sBase .. ".tab")
		if not(b and type(vT) == type({}) and vT.schema) then
			return nil
		end
		local t = {}
		for i, v in ipairs(vT.schema.fields) do
			if iRecord and vT.data[iRecord] then
				t[v.name] = vT.data[iRecord][i]
			else
				t[v.name] = i
			end
		end
		return t
	end
	function listRecords(sBase, sKey, bIndex)
		if not sBase then
			return nil
		end
		local b, vT = pcall(mw.ext.data.get, sBase .. "/key.tab")
		local vKT = b and type(vT) == type({}) and vT.data
		b, vT = pcall(mw.ext.data.get, sBase .. ".tab")
		if not(b and type(vT) == type({}) and vT.data) then
			return nil
		end
		local vFT = listFields(sBase)
		if not vFT then
			return nil
		end
		local t = {}
		for i, v in ipairs(vT.data) do
			if vKT then
				sKey = ""
				for iK, vK in ipairs(vKT) do
					sKey = sKey .. v[vFT[vK[1]]] or "" .. vK[2] or ""
				end
				t[sKey] = bIndex and i or v
			elseif vFT[sKey or "key"] then
				t[v[vFT[sKey or "key"]]] = bIndex and i or v
			else
				return nil
			end
		end
		return t
	end
	function selectTable(sBase, vKeyValue, nAdd, sKey)
		if not sBase then
			return nil
		end
		local sClip = tostring(sBase)
		if type(vKeyValue) == type(nil) then
			return nil
		end
		nAdd = tonumber(nAdd) or 0
		while nAdd == nAdd - 1 do
			nAdd = nAdd / 2
		end
		repeat
			local t = listRecords(sClip, sKey)
			if t and t[vKeyValue] then
				return t[vKeyValue]
			end
			sClip = (sClip and listFields(sClip .. "/info", 1) or {})["postClip"]
			sClip = sClip and string.sub(sClip, 6, -5)
		until not sClip
		if nAdd < 1 then
			return nil
		end
		sClip = tostring(sBase)
		local tNil = {}
		local b, vT = pcall(mw.ext.data.get, sClip .. "/nil.tab")
		if b and type(vT) == type({}) and vT.data then
			for i, v in ipairs(vT.data) do
				tNil[tostring(v[1])] = tostring(v[1])
			end
		end
		nAdd = nAdd - 1
		local t
		sClip = sClip .. "/add"
		repeat
			b, vT = pcall(mw.ext.data.get, sClip .. ".tab")
			if b and type(vT) == type({}) and vT.data then
				vT["schema"] = listFields(sClip)
				for i, v in ipairs(vT.data) do
					if type(v[vT.schema["keySum"] or 1]) == type(vKeyValue) and v[vT.schema["keySum"] or 1] == vKeyValue then
						local tT = {
							["fld"] = listFields(sBase),
							["val"] = selectTable(sBase, v[vT.schema["keySummand"] or 2], nAdd, sKey)
						}
						if tT.val then
							if t then
								for iF, vF in pairs(tT.fld) do
									if tNil[iF] then
										t[vF] = nil
									else
										if not type(t[vF]) == type(tT.val[vF]) then
											t[vF] = nil
										elseif type(t[vF]) == type(0) then
											t[vF] = t[vF] + tT.val[vF]
										elseif type(t[vF]) == type("") then
											t[vF] = t[vF] .. ", " .. tT.val[vF]
										else
											t[vF] = nil
										end
									end
								end
							else
								t = tT.val
							end
						else
							return nil
						end
					end
				end
			end
			sClip = (sClip and listFields(sClip .. "/info", 1) or {})["postClip"]
			sClip = sClip and string.sub(sClip, 6, -5)
		until not sClip
		return t
	end
	local tField = {
		["object error"] = "objectError",
		["selection error"] = "selectionError",
		["key error"] = "keyError",
		["field error"] = "fieldError",
		["key addition"] = "keyAddition",
		["arg 1"] = "arg1"
	}
	local sField = frame.args[5] or frame.args["field"]
	if tField[sField] then
		return frame.args[tField[sField]] or ""
	end
	local sBase = "Data"
	tField["object table link"] = "[[commons:Data:" .. sBase .. ".tab]]"
	if tField[sField] then
		return tField[sField]
	end
	local sObject = frame.args[1] or frame.args["object"]
	if sObject then
		local t = {
			["fld"] = listFields(sBase),
			["val"] = listRecords(sBase, "object")
		}
		local sClip = sBase
		while not t.val[sObject] do
			local tInfo = listFields(sClip .. "/info", 1)
			if not (tInfo and tInfo["postClip"]) then
				break
			end
			sClip = string.sub(tostring(tInfo["postClip"]), 6, -5)
			t.val = listRecords(sClip, "object")
		end
		if not t.val[sObject] then
			return frame.args["objectError"] or '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!object</span>'
		end
		if not t.val[sObject][t.fld["table"]] then
			return '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!table</span>'
		end
		sBase = string.sub(tostring(t.val[sObject][t.fld["table"]]), 6, -5)
		tField["selection table link"] = "[[commons:Data:" .. sBase .. ".tab]]"
		if tField[sField] then
			return tField[sField]
		end
		local vSelection = frame.args[2] or frame.args["selection"]
		local sSelectionName = frame.args["selectionName"]
		if not tonumber(vSelection) then
			sSelectionName = vSelection
		end
		vSelection = tonumber(vSelection)
		if vSelection or sSelectionName then
			t = {
				["fld"] = listFields(sBase),
				["val"] = listRecords(sBase, "selection"),
				["vnm"] = listRecords(sBase, "selectionName")
			}
			sClip = sBase
			while not (t.val[vSelection] or t.vnm[sSelectionName]) do
				local tInfo = listFields(sClip .. "/info", 1)
				if not (tInfo and tInfo["postClip"]) then
					break
				end
				sClip = string.sub(tostring(tInfo["postClip"]), 6, -5)
				t.val = listRecords(sClip, "selection")
				t.vnm = listRecords(sClip, "selectionName")
			end
			if not (t.val[vSelection] or t.vnm[sSelectionName]) then
				return frame.args["selectionError"] or '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!selection</span>'
			end
			if not (t.val[vSelection] or t.vnm[sSelectionName])[t.fld["table"]] then
				return '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!table</span>'
			end
			sBase = string.sub(tostring((t.val[vSelection] or t.vnm[sSelectionName])[t.fld["table"]]), 6, -5)
			tField["version table link"] = "[[commons:Data:" .. sBase .. ".tab]]"
			if tField[sField] then
				return tField[sField]
			end
			local vVersion = frame.args[3] or frame.args["version"]
			local sVersionDate = frame.args["versionDate"]
			if not tonumber(vVersion) then
				sVersionDate = vVersion
			end
			vVersion = tonumber(vVersion)
			if vVersion or sVersionDate or frame.args["current"] then
				local tInfo = listFields(sBase .. "/info", 1)
				if not (vVersion or sVersionDate) then
					vVersion = tonumber(tInfo["currentVersion"])
				end
				t = {
					["fld"] = listFields(sBase),
					["val"] = listRecords(sBase, "version"),
					["vdt"] = listRecords(sBase, "versionDate")
				}
				sClip = sBase
				while not (t.val[vVersion] or t.vdt[sVersionDate]) do
					tInfo = listFields(sClip .. "/info", 1)
					if not (tInfo and tInfo["postClip"]) then
						break
					end
					sClip = string.sub(tostring(tInfo["postClip"]), 6, -5)
					t.val = listRecords(sClip, "version")
					t.vdt = listRecords(sClip, "versionDate")
				end
				if not (t.val[vVersion] or t.vdt[sVersionDate]) then
					return frame.args["versionError"] or '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!version</span>'
				end
				if not (t.val[vVersion] or t.vdt[sVersionDate])[t.fld["table"]] then
					return '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!table</span>'
				end
				sBase = string.sub(tostring((t.val[vVersion] or t.vdt[sVersionDate])[t.fld["table"]]), 6, -5)
				tInfo = listFields(sBase .. "/info", 1)
				for i, v in pairs(tInfo) do
					tField[i .. " info"] = v
				end
				tField["value table link"] = "[[commons:Data:" .. sBase .. ".tab]]"
				if tField[sField] then
					return tField[sField]
				end
				local vKey = frame.args[4] or frame.args["key"]
				if vKey then
					t = {
						["fld"] = listFields(sBase),
						["val"] = selectTable(sBase, vKey, 0, "key"),
						["add"] = selectTable(sBase, vKey, 5, "key")
					}
					sClip = sBase
					while not (t.add and t.fld and t.add[t.fld[sField]]) do
						tInfo = listFields(sClip .. "/info", 1)
						if not (frame.args["tryOther"] and tInfo and tInfo["postVersion"]) then
							break
						end
						sClip = string.sub(tostring(tInfo["postVersion"]), 6, -5)
						t.val = selectTable(sClip, vKey, 0, "key")
						t.add = selectTable(sClip, vKey, 5, "key")
					end
					if t.fld and t.fld[sField] and not t.add then
						if vKey == "" then
							return ""
						end
						return frame.args["keyError"] or '<span class="error">[[commons:Data:' .. sBase .. '.tab]]!key*</span>'
					end
					if t.fld and t.fld[sField] then
						return t.add[t.fld[sField]]
					end
					tField["key note"] = (t.val or not t.add) and "" or frame.args["keyAddition"]
					if tField[sField] then
						return tField[sField]
					end
					for i, v in pairs(t.fld) do
						tField[i] = v
					end
				end
			end
		end
	end
	tField["field list"] = ""
	if tField[sField] then
		local s = ""
		local t = {}
		for i, v in pairs(tField) do
			t[#t + 1] = i
		end
		table.sort(t)
		for i, v in pairs(t) do
			s = s .. "* " .. v .. "\n"
		end
		return s
	end
	return frame.args["fieldError"] or '<span class="error">field = "field list"</span>'
end

function p.evaluate(frame)
	if tonumber(frame.args[1]) then
		return mw.getCurrentFrame():callParserFunction("#expr", mw.ustring.gsub(frame.args[2], "#", frame.args[1]))
	end
	return frame.args[1]
end

return p