Module:User:Theknightwho/dictionary

local class = require("Module:User:Theknightwho/middleclass")

local Dictionary = class("Dictionary")

function Dictionary:initialize(tableContentOrIndexType, valueType, tableContent) if (type(tableContentOrIndexType) == "string" and type(valueType) == "string") then rawset(self, "__table", tableContent or {}); self:setTypes(tableContentOrIndexType, valueType); else rawset(self, "__table", tableContentOrIndexType or {}); self:setTypes("*", "*"); end

rawset(self, "__name", ""); rawset(self, "count", #self.__table > 0 and #self.__table or (function local c = 0; for k in next, self.__table do			c = c + 1; end return c;	end)); end

function Dictionary:add(key, value) self[key] = value return self.__table[key] end

function Dictionary:remove(key) self[key] = nil end

function Dictionary:setTypes(keyType, valueType) rawset(self, "__types", {		key = keyType,		value = valueType	}) end

function Dictionary:foreach(callback) local hasStopped = false; local iteration = { ["stop"] = function hasStopped = true; end, ["source"] = self }	for k, v in next, self.__table do		callback(k, v, iteration); if (hasStopped) then break; end end end

function Dictionary:map(callback) local result = self.class result:setTypes("*", "*") local hasStopped = false local iteration = { ["stop"] = function hasStopped = true end, ["source"] = self, ["target"] = result };	for k, v in next, self.__table do		result[k] = callback(v, k, iteration) if (hasStopped) then break end end return result; end

function Dictionary:filter(callback) return self:map(function(v, k, iteration)		return callback(v, k) and v or nil;	end) end

function Dictionary:sort(comparator) table.sort(self.__table, comparator) return self end

function Dictionary:getKeys local result = self.class; result:setTypes("*", "*"); self:foreach(function(k, v)		result:add(result.count + 1, v);	end) return result; end

function Dictionary:getValues local result = self.class result:setTypes("*", "*") self:foreach(function(k, v)		result:add(result.count + 1, v)	end) return result end

function Dictionary:concat(separator) local str = ""; self:foreach(function(k, v)		str = str .. tostring(v) .. separator	end) return str:sub(1, #str - #separator) end

function Dictionary:__tostring local str = "{ Dictionary" .. (self.__name ~= "" and " " .. self.__name or "") .. " "	self:foreach(function(k, v)		str = str .. string.format("\n   [%s] = %s,", tostring(k), tostring(v))	end) return str .. "\n}" end

function Dictionary:__newindex(key, value) if (self.__types.key ~= "*" and not string.match(self.__types.key, type(key))) then error("Index of type \"" .. type(key) .. "\" is not accepted as dictionary" .. (self.__name ~= "" and " (" .. self.__name .. ")" or "") .. " requires it to be " .. self.__types.key .. ".", 2); end if (self.__types.value ~= "*" and type(value) ~= "nil" and not string.match(self.__types.value, type(value))) then error("Value of type \"" .. type(value) .. "\" is not accepted as dictionary" .. (self.__name ~= "" and " (" .. self.__name .. ")" or "") .. " requires it to be " .. self.__types.value .. ".", 2); end

if (self.__types.key == "*" and type(key) == "nil") then error("Attempt to index nil on a dictionary" .. (self.__name ~= "" and " (" .. self.__name .. ")" or "") .. ".", 2); end

if (type(value) == "nil" and type(self.__table[key]) ~= "nil") then self.count = self.count - 1; elseif (type(value) ~= "nil" and type(self.__table[key]) == "nil") then self.count = self.count + 1; end

self.__table[key] = value; end

return Dictionary