view DependencyLoader_Core/Core.lua @ 8:930871e163bc

created a new Tree class and started rearranging code
author mckenziemc
date Sat, 04 Dec 2010 23:05:34 -0800
parents 9852fcd5e59e
children
line wrap: on
line source



local addonName, addonTable = ...


local Core, core = addonTable:NewClass("Core")


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