view DependencyLoader/Tree.lua @ 16:1d8898cd1c82

removed the unused code from Core.lua
author mckenziemc
date Sat, 11 Dec 2010 01:54:15 -0800
parents a46bf694050c
children e7995d599184
line wrap: on
line source
--	Tree
--	Represents a recursive "tree" of addon 
--	dependencies rooted at a specific addon.


local addonName, addonTable = ...


--	FIXME: prevent infinite loops in the recursive functions


local Tree, tree = addonTable:NewClass("Tree")


local classes = addonTable.classes


Tree.trees = {}


---	(private) Creates a new tree object.
--	Assumptions: root addon exists and is not a Blizzard addon.
--	@param	root	Name, index, or Addon object of the root addon.
function Tree:New(root)
	if type(root) ~= "table" then
		root = classes.Addon:Get(root)
	end
	
	local instance = {}
	setmetatable(instance, self.instanceMetatable)
	
	instance.root = root
	
	return instance
end


---	Retrieves the tree rooted at the specified addon
--	Assumptions: root addon exists and is not a Blizzard addon
--	@param	root	Name, index, or Addon object of the root.
function Tree:Get(root)
	if type(root) ~= "table" then
		root = classes.Addon:Get(root)
	end
	
	local tree = self.trees[root]
	
	if tree then
		return tree
	else
		tree = self:New(root)
		self.trees[root] = tree
		return tree
	end
end


--	NOTE: All tree:Can functions should check the root too.
--	That way, the hooks don't have to do "if addon:Can_ and tree:Can_", 
--	plus the tree can cache info that includes the capabilities of the 
--	root addon.


---	Checks if the tree rooted at the specified addon 
--	can be loaded if all dependencies are enabled 
--	and the UI is reloaded.
--	Basically makes sure all dependencies are installed.
function tree:CanLoad()
	local root = self.root
	
	if root:IsLoaded() then
		return true
	end
	
	if not root:CanLoad() then
		return false
	end

	--	check all the dependencies
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		if not classes.Addon:Exists(depName) then
			return false
		end
		
		local dep = classes.Addon:Get(depName)
		local depTree = Tree:Get(dep)
		
		if not depTree:CanLoad() then
			return false
		end
	end
	
	return true
end


---	Checks if the tree can be loaded on demand.
--	Does not allow for force-loading; dependencies must 
--	already be loaded, or enabled and LoD.
function tree:CanLoD()
	local root = self.root
	
	if root:IsLoaded() then
		return true
	end
	
	if not root:CanLoD() then
		return false
	end
	
	--	now check dependencies recursively
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		if not classes.Addon:Exists(depName) then
			return false
		end
		
		local dep = classes.Addon:Get(depName)
		local depTree = Tree:Get(dep)
		
		if not depTree:CanLoD() then
			return false
		end
	end
	
	return true
end


---	Checks if this tree can be force-loaded.
--	Does not check user settings nor if force-loading is actually available.
--	@return	canForceLoad	True if this tree can be force loaded, false otherwise
function tree:CanForceLoad()
	local root = self.root
	--	TODO: remove redundencies (for now they're here for design flexibility)
	
	--	this addon must be loaded, able to load-on-demand, or able to force-load
	if root:IsLoaded() then
		return true
	end
	
	if not root:CanForceLoad() then
		return false
	end
	
	--	now check dependencies recursively
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		if not classes.Addon:Exists(depName) then
			return false
		end
		
		local dep = classes.Addon:Get(depName)
		local depTree = Tree:Get(dep)
		
		if not depTree:CanForceLoad() then
			return false
		end
	end
	
	return true
end


---	Prepares this tree to be loaded, whether through 
--	a ui reload or by loading on demand.
--	Assumptions: CanLoad is true for this tree
function tree:PrepareForLoad()
	local root = self.root
	
	--	The Addon class will take care of delaying enables 
	--	till after PLAYER_LOGIN if necessary.
	
	root:Enable()
	
	--	enable dependencies
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		Tree:Get(depName):PrepareForLoad()
	end

	--	prepare embeds, if they are available separately
	local embeds = {root:GetEmbeds(addon)}
	
	for i, embedName in pairs(embeds) do
		if classes.Addon:Exists(embedName) then
			Tree:Get(embedName):PrepareForLoad()
		end
	end
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

---	Force-loads this addon tree. If a subtree can be loaded on 
--	demand, this function will enable but not load the subtree.
--	Assumptions: the root addon should be force-loaded, not just enabled.
--function tree:ForceLoad()

--	Assumptions: the root is loadable-on demand, and force-load is available.
--	and tree can be force-loaded
function tree:PrepareForLoD()
	local root = self.root
	
	--	prepare dependencies first (for consistency)
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		local dep = classes.Addon:Get(depName)
		
		if not dep:IsLoaded() then
			if dep:CanLoD() then
				--	don't load it now but make sure its dependencies are prepared
				Tree:Get(dep):PrepareForLoD()
			else
				--	Based on our assumption about the tree, this addon 
				--	should be able to force-load.
				--	force-load it now so we can load the parent on demand
				Tree:Get(dep):ForceLoad()
			end
		end
	end

	--	prepare embeds, if they are available separately
	local embeds = {root:GetEmbeds()}
	
	for i, embedName in pairs(embeds) do
		if classes.Addon:Exists(embedName) then
			local embed = classes.Addon:Get(embedName)
			
			if not embed:IsLoaded() then
				if embed:CanLoD() then
					Tree:Get(embed):PrepareForLoD()
				else
					Tree:Get(embed):ForceLoad()
				end
			end
		end
	end

	root:Enable()
end


---	Force-loads this tree.
--	This will also load any LoD addons in the tree
function tree:ForceLoad()
	local root = self.root
	
	--	FIXME: if already loaded

	--	load dependencies
	local dependencies = {root:GetDependencies()}
	
	for i, depName in pairs(dependencies) do
		Tree:Get(depName):ForceLoad()
	end

	--	load embeds, if they are available separately
	local embeds = {root:GetEmbeds()}
	
	for i, embedName in pairs(embeds) do
		if classes.Addon:Exists(embedName) then
			Tree:Get(embedName):ForceLoad()
		end
	end
	
	root:ForceLoad()
end