diff DependencyLoader_Core/Core.lua @ 0:9852fcd5e59e

initial import
author mckenziemc
date Tue, 30 Nov 2010 16:13:04 -0800
parents
children 930871e163bc
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DependencyLoader_Core/Core.lua	Tue Nov 30 16:13:04 2010 -0800
@@ -0,0 +1,298 @@
+
+
+local addonName, addonTable = ...
+
+
+print("running Core.lua")
+
+--	TODO: prevent infinite loops in the recursive functions
+
+
+local Core, core = addonTable:NewClass("Core")
+
+local Addon = addonTable.classes.Addon
+
+function Core:New()
+	local instance = {}
+	setmetatable(instance, self.instanceMetatable)
+	
+	instance.addons = {}
+	instance.nameToIndex = {}
+	
+	for i=1,GetNumAddOns() do
+		local newAddon = Addon:New(i)
+		
+		instance.addons[i] = newAddon
+		instance.nameToIndex[newAddon:GetName()] = i
+	end
+	
+	--	TODO: enable dependencies for any addons that have already loaded
+	
+	return instance
+end
+
+
+--	@param	addon	Name or index of the addon to retrieve.
+--	@return 		The addon object, or nil if not found
+function core:GetAddon(addon)
+	if not Addon:Exists(addon) then
+		return nil
+	end
+	
+	local index
+
+	if type(addon) == "string" then
+		index = self.nameToIndex[addon]
+	elseif type(addon) == "number" then
+		index = addon
+	end
+	
+	return self.addons[index]
+end	
+
+
+--	Checks if the tree rooted at the specified addon can be force-loaded.
+--	@param	root	The name or index of the root addon.
+function core:CanForceLoadTree(root)
+	--	convert root to an Addon object
+	root = self:GetAddon(root)
+	assert(root)
+	
+	if root:IsLoaded() then
+		return true
+	end
+	
+	--	check if the root itself can be force-loaded
+	if not root:CanForceLoad() then
+		return false
+	end
+	
+	--	now check dependencies recursively
+	--	FIXME: prevent infinite recursion
+
+	local dependencies = {root:GetDependencies()}
+	for i, depName in pairs(dependencies) do
+		local dep = self:GetAddon(depName)
+		
+		if dep == nil then
+			return false		--	missing dependency
+		end
+		
+		--	if it's already loaded then skip to next one
+		if not dep:IsLoaded() then
+			if not self:CanForceLoadTree(depName) then
+				return false
+			end
+		end
+	end
+	
+	return true
+end
+
+--	NOTE: any tree that can be loaded on demand is also eligible for force-loading
+--	Checks if the tree rooted at the specified addon can be loaded on demand.
+--	@param	root	The name or index of the root addon.
+function core:CanLoDTree(root)
+	root = self:GetAddon(root)
+	assert(root)
+
+	--	since this will be used recursively, return true if 
+	--	this is already loaded.
+	if root:IsLoaded() then
+		return true
+	end
+	
+	--	true if all dependencies are loaded or LoD
+	
+	if not root:CanLoD() then
+		return false
+	end
+	
+	--	now check dependencies recursively
+	local dependencies = {root:GetDependencies()}
+	for i, depName in pairs(dependencies) do
+		local dep = self:GetAddon(depName)
+		
+		if not dep then
+			return false		--	missing
+		end
+		
+		if not dep:IsLoaded() then
+			if not self:CanLoDTree(depName) then
+				return false
+			end
+		end
+	end
+	
+	return true
+end
+
+
+--	Checks if the tree rooted at the specified addon 
+--	can be loaded if all dependencies are enabled 
+--	the UI is reloaded.
+--	Basically makes sure all dependencies are installed.
+function core:CanReloadTree(root)
+	--	convert root to an Addon object
+	root = self:GetAddon(root)
+	assert(root)
+	
+	if root:IsLoaded() then
+		return true
+		--	FIXME: 	deps may have been disabled
+	end
+	
+	--	TODO: make sure the root isn't incompatible
+	
+	--	now check dependencies recursively
+	--	FIXME: prevent infinite recursion
+
+	local dependencies = {root:GetDependencies()}
+	for i, depName in pairs(dependencies) do
+		local dep = self:GetAddon(depName)
+		
+		if dep == nil then
+			return false		--	missing dependency
+		end
+
+		--	TODO: make sure it's compatible
+	end
+	
+	return true
+end
+
+--	Loads the tree rooted at the specified addon.
+--	FIXME: load the root too or not?
+--	Supports both LoD addons and those that require force-loading.
+function core:LoadTree(addon)
+	--	don't check if the tree can actually be loaded.
+	--	external code should do that itself to check if it 
+	--	should even call this at all.
+
+	if self:ForceLoadAvailable() then
+		--	LoD trees can also be force-loaded
+		self:ForceLoadTree(addon)
+	else
+		self:LoadLoDTree(addon)
+	end
+end
+
+
+--	load the root too, since it may actually be a leaf
+function core:ForceLoadTree(root)
+	root = self:GetAddon(root)
+	assert(root)
+	
+	--	load dependencies
+	local dependencies = {root:GetDependencies(addon)}
+	for i, depName in pairs(dependencies) do
+		self:ForceLoadTree(depName)
+	end
+
+	--	load embeds, if they are available separately
+	local embeds = {root:GetEmbeds(addon)}
+	for i, embedName in pairs(embeds) do
+		if Addon:Exists(embedName) then
+			self:ForceLoadTree(embedName)
+		end
+	end
+	
+	root:ForceLoad()
+end
+
+
+function core:LoadLoDTree(root)
+	root = self:GetAddon(root)
+	assert(root)
+	
+	--	load dependencies
+	local dependencies = {root:GetDependencies(addon)}
+	for i, depName in pairs(dependencies) do
+		self:LoadLoDTree(depName)
+	end
+
+	--	load embeds, if they are available separately
+	local embeds = {root:GetEmbeds(addon)}
+	for i, embedName in pairs(embeds) do
+		if Addon:Exists(embedName) then
+			self:LoadLoDTree(embedName)
+		end
+	end
+	
+	root:LoD()
+end
+
+
+--	I think the problem this solves is a major issue with 
+--	migrating to separate libs. think about it more and document 
+--	here and in project description
+function core:PrepareLoDTree(root)
+	root = self:GetAddon(root)
+	assert(root)
+	
+	--	assume root is LoD
+	
+	--	check dependencies
+	local dependencies = {root:GetDependencies(addon)}
+	for i, depName in pairs(dependencies) do
+		local dep = self:GetAddon(depName)
+		
+		--	assume external code made sure it exists
+		
+		if dep:CanLoD() then
+			--	don't load it now but make sure its dependencies are prepared
+			self:PrepareLoDTree(depName)
+		else
+			--	FIXME: if it's already loaded
+			--	force-load it now so we can load the parent on demand
+			self:ForceLoadTree(depName)
+		end
+	end
+
+	--	prepare embeds, if they are available separately
+	local embeds = {root:GetEmbeds(addon)}	--	FIXME: addon?
+	for i, embedName in pairs(embeds) do
+		local embed = self:GetAddon(embedName)
+		
+		if embed then
+			if embed:CanLoD() then
+				--	don't load it now but make sure its dependencies are prepared
+				self:PrepareLoDTree(embedName)
+			else
+				--	FIXME: if it's already loaded
+				--	force-load it now so we can load the parent on demand
+				self:ForceLoadTree(depName)
+			end
+		end
+	end
+end
+
+
+function Core:PrepareReloadTree(addon)
+	root = self:GetAddon(root)
+	assert(root)
+	
+	root:Enable()
+	
+	--	check dependencies
+	local dependencies = {root:GetDependencies()}
+	for i, depName in pairs(dependencies) do
+		self:PrepareReloadTree(depName)
+	end
+
+	--	prepare embeds, if they are available separately
+	local embeds = {root:GetEmbeds(addon)}
+	for i, embedName in pairs(embeds) do
+		local embed = self:GetAddon(embedName)
+		
+		if embed then
+			self:PrepareReloadTree(embedName)
+		end
+	end
+end
+
+
+function Core:ForceLoadAvailable()
+	return true
+	--	FIXME: use field and a frame registered for PLAYER_LOGIN
+end