annotate DependencyLoader/Tree.lua @ 11:47d15fc9208e

updated the .pkgmeta to reflect the directory changes added LibScriptLink external changed the main module's Dependencies to OptDeps moved embeds.xml and Ace3.xml
author mckenziemc
date Sun, 05 Dec 2010 03:39:26 -0800
parents e0a4a8b5b389
children b230b94d4487
rev   line source
mckenziemc@8 1 -- Tree
mckenziemc@8 2 -- Represents a recursive "tree" of addon
mckenziemc@8 3 -- dependencies rooted at a specific addon.
mckenziemc@8 4
mckenziemc@8 5
mckenziemc@8 6 local addonName, addonTable = ...
mckenziemc@8 7
mckenziemc@8 8
mckenziemc@10 9 -- FIXME: prevent infinite loops in the recursive functions
mckenziemc@8 10
mckenziemc@8 11
mckenziemc@8 12 local Tree, tree = addonTable:NewClass("Tree")
mckenziemc@8 13
mckenziemc@8 14
mckenziemc@8 15 Tree.trees = {}
mckenziemc@8 16
mckenziemc@10 17
mckenziemc@8 18 -- internal
mckenziemc@8 19 -- Creates a new tree object
mckenziemc@8 20 -- @param root Name, index, or Addon object of the root addon.
mckenziemc@8 21 function Tree:New(root)
mckenziemc@8 22 if type(root) ~= "table" then
mckenziemc@8 23 root = addonTable.classes.Addon:Get(root)
mckenziemc@8 24 end
mckenziemc@8 25
mckenziemc@8 26 local instance = {}
mckenziemc@8 27 setmetatable(instance, self.instanceMetatable)
mckenziemc@8 28
mckenziemc@8 29 instance.root = root
mckenziemc@8 30
mckenziemc@8 31 return instance
mckenziemc@8 32 end
mckenziemc@8 33
mckenziemc@8 34
mckenziemc@8 35 --- Retrieves the tree rooted at the specified addon
mckenziemc@8 36 -- @param root Name, index, or Addon object of the root.
mckenziemc@8 37 function Tree:Get(root)
mckenziemc@8 38 if type(root) ~= "table" then
mckenziemc@8 39 root = addonTable.classes.Addon:Get(root)
mckenziemc@8 40 end
mckenziemc@8 41
mckenziemc@8 42 local tree = self.trees[root]
mckenziemc@8 43
mckenziemc@8 44 if tree then
mckenziemc@8 45 return tree
mckenziemc@8 46 else
mckenziemc@8 47 tree = self:New(root)
mckenziemc@8 48 self.trees[root] = tree
mckenziemc@8 49 return tree
mckenziemc@8 50 end
mckenziemc@8 51 end
mckenziemc@8 52
mckenziemc@8 53
mckenziemc@8 54 function tree:GetLoadBitfield()
mckenziemc@8 55 local bitfield = self.root:GetLoadBitfield()
mckenziemc@8 56
mckenziemc@8 57 local dependencies = {self.root:GetDependencies()}
mckenziemc@8 58 for i, depName in pairs(dependencies) do
mckenziemc@8 59 local depTree = Tree:Get(depName)
mckenziemc@8 60
mckenziemc@8 61 if depTree == nil then
mckenziemc@8 62 return 0
mckenziemc@8 63 end
mckenziemc@8 64
mckenziemc@8 65 bitfield = bit.band(bitfield, depTree:GetLoadBitfield())
mckenziemc@8 66 end
mckenziemc@8 67
mckenziemc@8 68 return bitfield
mckenziemc@8 69 end
mckenziemc@8 70
mckenziemc@8 71
mckenziemc@10 72 --- Checks if this tree can be force-loaded.
mckenziemc@10 73 -- Does not check user settings nor if force-loading is actually available.
mckenziemc@10 74 -- @return canForceLoad True if this tree can be force loaded, false otherwise
mckenziemc@10 75 function tree:CanForceLoad()
mckenziemc@10 76 if self.root:IsLoaded() then
mckenziemc@10 77 return true
mckenziemc@10 78 end
mckenziemc@10 79
mckenziemc@10 80 if not self.root:CanForceLoad() then
mckenziemc@10 81 return false
mckenziemc@10 82 end
mckenziemc@10 83
mckenziemc@10 84 -- now check dependencies recursively
mckenziemc@10 85 local dependencies = {self.root:GetDependencies()}
mckenziemc@10 86 for i, depName in pairs(dependencies) do
mckenziemc@10 87 local depTree = Tree:Get(depName)
mckenziemc@10 88
mckenziemc@10 89 if not depTree:CanForceLoad() then
mckenziemc@10 90 return false
mckenziemc@10 91 end
mckenziemc@10 92 end
mckenziemc@10 93
mckenziemc@10 94 return
mckenziemc@8 95 end
mckenziemc@8 96
mckenziemc@8 97
mckenziemc@8 98 -- NOTE: any tree that can be loaded on demand is also eligible for force-loading
mckenziemc@10 99 -- Checks if the tree can be loaded on demand.
mckenziemc@10 100 function tree:CanLoD()
mckenziemc@8 101 -- since this will be used recursively, return true if
mckenziemc@8 102 -- this is already loaded.
mckenziemc@10 103 if self.root:IsLoaded() then
mckenziemc@8 104 return true
mckenziemc@8 105 end
mckenziemc@8 106
mckenziemc@8 107 -- true if all dependencies are loaded or LoD
mckenziemc@8 108
mckenziemc@10 109 if not self.root:CanLoD() then
mckenziemc@8 110 return false
mckenziemc@8 111 end
mckenziemc@8 112
mckenziemc@8 113 -- now check dependencies recursively
mckenziemc@8 114 local dependencies = {root:GetDependencies()}
mckenziemc@8 115 for i, depName in pairs(dependencies) do
mckenziemc@10 116 local depTree = Tree:Get(depName)
mckenziemc@8 117
mckenziemc@10 118 if not depTree:CanLoD() then
mckenziemc@10 119 return false
mckenziemc@8 120 end
mckenziemc@8 121 end
mckenziemc@8 122
mckenziemc@8 123 return true
mckenziemc@8 124 end
mckenziemc@8 125
mckenziemc@8 126
mckenziemc@8 127 -- Checks if the tree rooted at the specified addon
mckenziemc@8 128 -- can be loaded if all dependencies are enabled
mckenziemc@8 129 -- the UI is reloaded.
mckenziemc@8 130 -- Basically makes sure all dependencies are installed.
mckenziemc@10 131 function tree:CanLoad()
mckenziemc@10 132 if self.root:IsLoaded() then
mckenziemc@8 133 return true
mckenziemc@8 134 -- FIXME: deps may have been disabled
mckenziemc@8 135 end
mckenziemc@8 136
mckenziemc@8 137 -- TODO: make sure the root isn't incompatible
mckenziemc@8 138
mckenziemc@8 139 -- now check dependencies recursively
mckenziemc@8 140 -- FIXME: prevent infinite recursion
mckenziemc@8 141
mckenziemc@10 142 local dependencies = {self.root:GetDependencies()}
mckenziemc@8 143 for i, depName in pairs(dependencies) do
mckenziemc@10 144 local depTree = Tree:Get(depName)
mckenziemc@8 145
mckenziemc@10 146 if not depTree:CanLoad() then
mckenziemc@8 147 return false -- missing dependency
mckenziemc@8 148 end
mckenziemc@8 149
mckenziemc@8 150 -- TODO: make sure it's compatible
mckenziemc@8 151 end
mckenziemc@8 152
mckenziemc@8 153 return true
mckenziemc@8 154 end
mckenziemc@8 155
mckenziemc@10 156 --[[
mckenziemc@8 157 -- Loads the tree rooted at the specified addon.
mckenziemc@8 158 -- FIXME: load the root too or not?
mckenziemc@8 159 -- Supports both LoD addons and those that require force-loading.
mckenziemc@10 160 function tree:Load(addon)
mckenziemc@8 161 -- don't check if the tree can actually be loaded.
mckenziemc@8 162 -- external code should do that itself to check if it
mckenziemc@8 163 -- should even call this at all.
mckenziemc@8 164
mckenziemc@8 165 if self:ForceLoadAvailable() then
mckenziemc@8 166 -- LoD trees can also be force-loaded
mckenziemc@8 167 self:ForceLoadTree(addon)
mckenziemc@8 168 else
mckenziemc@8 169 self:LoadLoDTree(addon)
mckenziemc@8 170 end
mckenziemc@8 171 end
mckenziemc@10 172 ]]
mckenziemc@8 173
mckenziemc@8 174
mckenziemc@8 175 -- load the root too, since it may actually be a leaf
mckenziemc@10 176 function tree:ForceLoad()
mckenziemc@8 177 -- load dependencies
mckenziemc@10 178 local dependencies = {self.root:GetDependencies()}
mckenziemc@8 179 for i, depName in pairs(dependencies) do
mckenziemc@10 180 local depTree = Tree:Get(depName)
mckenziemc@10 181 depTree:ForceLoad()
mckenziemc@8 182 end
mckenziemc@8 183
mckenziemc@8 184 -- load embeds, if they are available separately
mckenziemc@10 185 local embeds = {self.root:GetEmbeds()}
mckenziemc@8 186 for i, embedName in pairs(embeds) do
mckenziemc@10 187 local embedTree = Tree:Get(embedName)
mckenziemc@10 188 embedTree:ForceLoad()
mckenziemc@8 189 end
mckenziemc@8 190
mckenziemc@8 191 root:ForceLoad()
mckenziemc@8 192 end
mckenziemc@8 193
mckenziemc@8 194
mckenziemc@10 195 --[[ don't think i need this
mckenziemc@8 196 function core:LoadLoDTree(root)
mckenziemc@8 197 root = self:GetAddon(root)
mckenziemc@8 198 assert(root)
mckenziemc@8 199
mckenziemc@8 200 -- load dependencies
mckenziemc@8 201 local dependencies = {root:GetDependencies(addon)}
mckenziemc@8 202 for i, depName in pairs(dependencies) do
mckenziemc@8 203 self:LoadLoDTree(depName)
mckenziemc@8 204 end
mckenziemc@8 205
mckenziemc@8 206 -- load embeds, if they are available separately
mckenziemc@8 207 local embeds = {root:GetEmbeds(addon)}
mckenziemc@8 208 for i, embedName in pairs(embeds) do
mckenziemc@8 209 if Addon:Exists(embedName) then
mckenziemc@8 210 self:LoadLoDTree(embedName)
mckenziemc@8 211 end
mckenziemc@8 212 end
mckenziemc@8 213
mckenziemc@8 214 root:LoD()
mckenziemc@8 215 end
mckenziemc@10 216 ]]
mckenziemc@8 217
mckenziemc@8 218
mckenziemc@8 219 -- I think the problem this solves is a major issue with
mckenziemc@8 220 -- migrating to separate libs. think about it more and document
mckenziemc@8 221 -- here and in project description
mckenziemc@10 222 function tree:PrepareForLoD()
mckenziemc@8 223 -- assume root is LoD
mckenziemc@8 224
mckenziemc@8 225 -- check dependencies
mckenziemc@8 226 local dependencies = {root:GetDependencies(addon)}
mckenziemc@8 227 for i, depName in pairs(dependencies) do
mckenziemc@10 228 local depTree = Tree:Get(depName)
mckenziemc@10 229 depTree:PrepareForLoD()
mckenziemc@8 230
mckenziemc@10 231 --[[
mckenziemc@8 232 if dep:CanLoD() then
mckenziemc@8 233 -- don't load it now but make sure its dependencies are prepared
mckenziemc@8 234 self:PrepareLoDTree(depName)
mckenziemc@8 235 else
mckenziemc@8 236 -- FIXME: if it's already loaded
mckenziemc@8 237 -- force-load it now so we can load the parent on demand
mckenziemc@8 238 self:ForceLoadTree(depName)
mckenziemc@8 239 end
mckenziemc@10 240 ]]
mckenziemc@8 241 end
mckenziemc@8 242
mckenziemc@8 243 -- prepare embeds, if they are available separately
mckenziemc@8 244 local embeds = {root:GetEmbeds(addon)} -- FIXME: addon?
mckenziemc@8 245 for i, embedName in pairs(embeds) do
mckenziemc@10 246 local embedTree = Tree:Get(embedName)
mckenziemc@10 247 embedTree:PrepareForLoD()
mckenziemc@8 248
mckenziemc@10 249 --[[
mckenziemc@8 250 if embed then
mckenziemc@8 251 if embed:CanLoD() then
mckenziemc@8 252 -- don't load it now but make sure its dependencies are prepared
mckenziemc@8 253 self:PrepareLoDTree(embedName)
mckenziemc@8 254 else
mckenziemc@8 255 -- FIXME: if it's already loaded
mckenziemc@8 256 -- force-load it now so we can load the parent on demand
mckenziemc@8 257 self:ForceLoadTree(depName)
mckenziemc@8 258 end
mckenziemc@8 259 end
mckenziemc@10 260 ]]
mckenziemc@8 261 end
mckenziemc@8 262 end
mckenziemc@8 263
mckenziemc@8 264
mckenziemc@10 265 function tree:PrepareForReload()
mckenziemc@10 266 self.root:Enable()
mckenziemc@8 267
mckenziemc@8 268 -- check dependencies
mckenziemc@10 269 local dependencies = {self.root:GetDependencies()}
mckenziemc@8 270 for i, depName in pairs(dependencies) do
mckenziemc@10 271 Tree:Get(depName):PrepareForReload()
mckenziemc@8 272 end
mckenziemc@8 273
mckenziemc@8 274 -- prepare embeds, if they are available separately
mckenziemc@10 275 local embeds = {self.root:GetEmbeds(addon)}
mckenziemc@8 276 for i, embedName in pairs(embeds) do
mckenziemc@10 277 Tree:Get(embedName):PrepareForReload()
mckenziemc@8 278 end
mckenziemc@8 279 end