annotate DependencyLoader/Tree.lua @ 10:e0a4a8b5b389

lots more modifications...
author mckenziemc
date Sun, 05 Dec 2010 03:10:07 -0800
parents 5362e308c3eb
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