module-cluster 1.4.8 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/README.md +127 -337
  2. data/lib/module-cluster.rb +1 -153
  3. data/lib/module/cluster.rb +341 -0
  4. data/lib/module/cluster/class_support.rb +22 -0
  5. data/lib/module/cluster/cluster.rb +10 -0
  6. data/lib/module/cluster/cluster/cluster_interface.rb +550 -0
  7. data/lib/module/cluster/exception/module_not_in_stack.rb +26 -0
  8. data/lib/module/cluster/instance_controller.rb +14 -0
  9. data/lib/module/cluster/instance_controller/hook_controller.rb +33 -0
  10. data/lib/module/cluster/instance_controller/hook_controller/chain_proxy.rb +511 -0
  11. data/lib/module/cluster/instance_controller/hook_controller/hook_controller_interface.rb +830 -0
  12. data/lib/module/cluster/instance_controller/instance_controller_interface.rb +269 -0
  13. data/lib/module/cluster/instance_controller/multiple_hook_controller_proxy.rb +359 -0
  14. data/lib/module/cluster/instance_controller/multiple_hook_controller_proxy/chain_proxy.rb +442 -0
  15. data/lib/module/cluster/module_support.rb +67 -0
  16. data/lib/module/namespaces.rb +13 -0
  17. data/lib/module/requires.rb +32 -0
  18. data/spec/module/cluster/cluster_spec.rb +473 -0
  19. data/spec/module/cluster/instance_controller/hook_controller_spec.rb +922 -0
  20. data/spec/module/cluster/instance_controller/multiple_hook_controller_proxy_spec.rb +1240 -0
  21. data/spec/module/cluster_spec.rb +1794 -0
  22. metadata +27 -98
  23. data/README.rdoc +0 -395
  24. data/lib/module-cluster/ModuleCluster.rb +0 -9
  25. data/lib/module-cluster/ModuleCluster/Define.rb +0 -12
  26. data/lib/module-cluster/ModuleCluster/Define/Block.rb +0 -9
  27. data/lib/module-cluster/ModuleCluster/Define/Block/CascadingClass.rb +0 -83
  28. data/lib/module-cluster/ModuleCluster/Define/Block/CascadingClassOrModule.rb +0 -70
  29. data/lib/module-cluster/ModuleCluster/Define/Block/CascadingModule.rb +0 -79
  30. data/lib/module-cluster/ModuleCluster/Define/Block/CascadingModuleOrSubclass.rb +0 -21
  31. data/lib/module-cluster/ModuleCluster/Define/Block/Class.rb +0 -77
  32. data/lib/module-cluster/ModuleCluster/Define/Block/ClassOrInstance.rb +0 -78
  33. data/lib/module-cluster/ModuleCluster/Define/Block/ClassOrModule.rb +0 -78
  34. data/lib/module-cluster/ModuleCluster/Define/Block/ClassOrModuleOrInstance.rb +0 -78
  35. data/lib/module-cluster/ModuleCluster/Define/Block/ClassOrModuleOrSubclass.rb +0 -36
  36. data/lib/module-cluster/ModuleCluster/Define/Block/ClassOrSubclass.rb +0 -29
  37. data/lib/module-cluster/ModuleCluster/Define/Block/Instance.rb +0 -45
  38. data/lib/module-cluster/ModuleCluster/Define/Block/Module.rb +0 -77
  39. data/lib/module-cluster/ModuleCluster/Define/Block/ModuleOrInstance.rb +0 -78
  40. data/lib/module-cluster/ModuleCluster/Define/Block/ModuleOrSubclass.rb +0 -29
  41. data/lib/module-cluster/ModuleCluster/Define/Block/Subclass.rb +0 -56
  42. data/lib/module-cluster/ModuleCluster/Define/ClassCluster.rb +0 -193
  43. data/lib/module-cluster/ModuleCluster/Define/ClassOrInstanceCluster.rb +0 -128
  44. data/lib/module-cluster/ModuleCluster/Define/Cluster.rb +0 -181
  45. data/lib/module-cluster/ModuleCluster/Define/ClusterCascades.rb +0 -185
  46. data/lib/module-cluster/ModuleCluster/Define/ClusterCascadesToClass.rb +0 -181
  47. data/lib/module-cluster/ModuleCluster/Define/ClusterCascadesToModule.rb +0 -181
  48. data/lib/module-cluster/ModuleCluster/Define/Deprecated.rb +0 -40
  49. data/lib/module-cluster/ModuleCluster/Define/InstanceCluster.rb +0 -45
  50. data/lib/module-cluster/ModuleCluster/Define/ModuleCluster.rb +0 -193
  51. data/lib/module-cluster/ModuleCluster/Define/ModuleOrClassCluster.rb +0 -209
  52. data/lib/module-cluster/ModuleCluster/Define/ModuleOrInstanceCluster.rb +0 -128
  53. data/lib/module-cluster/ModuleCluster/Define/Status.rb +0 -106
  54. data/lib/module-cluster/ModuleCluster/Suspend.rb +0 -7
  55. data/lib/module-cluster/ModuleCluster/Suspend/Hooks.rb +0 -315
  56. data/lib/module-cluster/ModuleCluster/Suspend/WithoutHooks.rb +0 -153
  57. data/lib/module-cluster/_private_/ModuleCluster/CascadeFeatures.rb +0 -77
  58. data/lib/module-cluster/_private_/ModuleCluster/CascadeFeatures/ClusterStack.rb +0 -44
  59. data/lib/module-cluster/_private_/ModuleCluster/CascadeFeatures/PerformCascades.rb +0 -292
  60. data/lib/module-cluster/_private_/ModuleCluster/CascadeFeatures/Subclass.rb +0 -24
  61. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack.rb +0 -12
  62. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block.rb +0 -9
  63. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block/Class.rb +0 -36
  64. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block/Inherited.rb +0 -20
  65. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block/Instance.rb +0 -20
  66. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block/Module.rb +0 -36
  67. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Block/Set.rb +0 -6
  68. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Extends.rb +0 -140
  69. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Includes.rb +0 -110
  70. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/PrependsExtends.rb +0 -140
  71. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/PrependsIncludes.rb +0 -110
  72. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Set.rb +0 -35
  73. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Set/MultiSetProxy.rb +0 -359
  74. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Status.rb +0 -55
  75. data/lib/module-cluster/_private_/ModuleCluster/ClusterStack/Suspend.rb +0 -199
  76. data/lib/module-cluster/_private_/ModuleCluster/ExtendForCascade.rb +0 -34
  77. data/spec/ModuleCluster/Define/Block/CascadingClassOrModule_spec.rb +0 -285
  78. data/spec/ModuleCluster/Define/Block/CascadingClass_spec.rb +0 -254
  79. data/spec/ModuleCluster/Define/Block/CascadingModuleOrSubclass_spec.rb +0 -56
  80. data/spec/ModuleCluster/Define/Block/CascadingModule_spec.rb +0 -278
  81. data/spec/ModuleCluster/Define/Block/ClassOrInstance_spec.rb +0 -230
  82. data/spec/ModuleCluster/Define/Block/ClassOrModuleOrInstance_spec.rb +0 -238
  83. data/spec/ModuleCluster/Define/Block/ClassOrModuleOrSubclass_spec.rb +0 -54
  84. data/spec/ModuleCluster/Define/Block/ClassOrModule_spec.rb +0 -231
  85. data/spec/ModuleCluster/Define/Block/ClassOrSubclass_spec.rb +0 -54
  86. data/spec/ModuleCluster/Define/Block/Class_spec.rb +0 -224
  87. data/spec/ModuleCluster/Define/Block/Instance_spec.rb +0 -78
  88. data/spec/ModuleCluster/Define/Block/ModuleOrInstance_spec.rb +0 -54
  89. data/spec/ModuleCluster/Define/Block/ModuleOrSubclass_spec.rb +0 -51
  90. data/spec/ModuleCluster/Define/Block/Module_spec.rb +0 -230
  91. data/spec/ModuleCluster/Define/Block/Subclass_spec.rb +0 -73
  92. data/spec/ModuleCluster/Define/Block_spec.rb +0 -18
  93. data/spec/ModuleCluster/Define/ClassCluster_spec.rb +0 -728
  94. data/spec/ModuleCluster/Define/ClassOrInstanceCluster_spec.rb +0 -576
  95. data/spec/ModuleCluster/Define/ClusterCascadesToClass_spec.rb +0 -659
  96. data/spec/ModuleCluster/Define/ClusterCascadesToModule_spec.rb +0 -678
  97. data/spec/ModuleCluster/Define/ClusterCascades_spec.rb +0 -644
  98. data/spec/ModuleCluster/Define/Cluster_spec.rb +0 -708
  99. data/spec/ModuleCluster/Define/InstanceCluster_spec.rb +0 -102
  100. data/spec/ModuleCluster/Define/ModuleCluster_spec.rb +0 -728
  101. data/spec/ModuleCluster/Define/ModuleOrClassCluster_spec.rb +0 -728
  102. data/spec/ModuleCluster/Define/ModuleOrInstanceCluster_spec.rb +0 -576
  103. data/spec/ModuleCluster/Suspend/Hooks_spec.rb +0 -573
  104. data/spec/ModuleCluster/Suspend/WithoutHooks_spec.rb +0 -559
  105. data/spec/ModuleCluster_spec.rb +0 -15
  106. data/spec/_private_/ModuleCluster/CascadeFeatures/PerformCascades_spec.rb +0 -386
  107. data/spec/_private_/ModuleCluster/ClusterStack/Set/MultiSetProxy_spec.rb +0 -419
  108. data/spec/_private_/ModuleCluster/ClusterStack/Suspend_spec.rb +0 -242
@@ -0,0 +1,830 @@
1
+
2
+ ###
3
+ # Interface implementation for
4
+ # {::Module::Cluster::InstanceController::HookController Module::Cluster::InstanceController::HookController}.
5
+ # Implementation provided separately for ease of overloading.
6
+ #
7
+ module ::Module::Cluster::InstanceController::HookController::HookControllerInterface
8
+
9
+ ###
10
+ # Struct used to store event frames for processing at time of event (include/extend/subclass).
11
+ #
12
+ FrameStruct = ::Struct.new( :owner, :cluster, :context, :cascades, :block, :module, :action )
13
+
14
+ ################
15
+ # initialize #
16
+ ################
17
+
18
+ ###
19
+ # @private
20
+ #
21
+ # @param name Name of this Hook Controller.
22
+ #
23
+ # @param parent_instance_controller Instance controller for which this Hook Controller is operative.
24
+ #
25
+ def initialize( name, parent_instance_controller )
26
+
27
+ @name = name
28
+
29
+ @parent_instance_controller = parent_instance_controller
30
+
31
+ @instance = @parent_instance_controller.instance
32
+
33
+ @stack = [ ]
34
+
35
+ @extend_modules = { }
36
+ @include_modules = { }
37
+
38
+ end
39
+
40
+ #############
41
+ # include #
42
+ #############
43
+
44
+ ###
45
+ # Declare that modules should be included at event hook.
46
+ #
47
+ # @overload include( module, ..., & block )
48
+ #
49
+ # @param module Module to include at event hook.
50
+ #
51
+ # @yield [hooked_instance] Block for event hook action.
52
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
53
+ # Equivalent to parameter for #included and #extended.
54
+ #
55
+ # @return [Module::Cluster::InstanceController::HookController] self
56
+ #
57
+ def include( *modules, & block )
58
+
59
+ include_at_index( -1, nil, nil, nil, false, *modules, & block )
60
+
61
+ return self
62
+
63
+ end
64
+
65
+ ############
66
+ # extend #
67
+ ############
68
+
69
+ ###
70
+ # Declare that modules should be extended at event hook.
71
+ #
72
+ # @overload extend( module, ..., & block )
73
+ #
74
+ # @param module Module to extend at event hook.
75
+ #
76
+ # @yield [hooked_instance] Block for event hook action.
77
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
78
+ # Equivalent to parameter for #included and #extended.
79
+ #
80
+ # @return [Module::Cluster::InstanceController::HookController] self
81
+ #
82
+ def extend( *modules, & block )
83
+
84
+ extend_at_index( -1, nil, nil, nil, false, *modules, & block )
85
+
86
+ return self
87
+
88
+ end
89
+
90
+ ########################
91
+ # include_and_extend #
92
+ ########################
93
+
94
+ ###
95
+ # Declare that modules should be included and extended at event hook. See also #extend_and_include.
96
+ #
97
+ # @overload include_and_extend( module, ..., & block )
98
+ #
99
+ # @param module Module to include and extend at event hook.
100
+ #
101
+ # @yield [hooked_instance] Block for event hook action.
102
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
103
+ # Equivalent to parameter for #included and #extended.
104
+ #
105
+ # @return [Module::Cluster::InstanceController::HookController] self
106
+ #
107
+ def include_and_extend( *modules, & block )
108
+
109
+ modules.each do |this_module|
110
+ include( this_module, & block )
111
+ extend( this_module, & block )
112
+ end
113
+
114
+ return self
115
+
116
+ end
117
+
118
+ ########################
119
+ # extend_and_include #
120
+ ########################
121
+
122
+ ###
123
+ # Declare that modules should be extended and included at event hook. Order is reversed from #include_and_extend.
124
+ #
125
+ # @overload extend_and_include( module, ..., & block )
126
+ #
127
+ # @param module Module to extend and include at event hook.
128
+ #
129
+ # @yield [hooked_instance] Block for event hook action.
130
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
131
+ # Equivalent to parameter for #included and #extended.
132
+ #
133
+ # @return [Module::Cluster::InstanceController::HookController] self
134
+ #
135
+ def extend_and_include( *modules, & block )
136
+
137
+ modules.each do |this_module|
138
+ extend( this_module, & block )
139
+ include( this_module, & block )
140
+ end
141
+
142
+ return self
143
+
144
+ end
145
+
146
+ ############
147
+ # action #
148
+ ############
149
+
150
+ ###
151
+ # Declare that action should be performed at event hook.
152
+ #
153
+ # @yield [hooked_instance] Block for event hook action.
154
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
155
+ # Equivalent to parameter for #included and #extended.
156
+ #
157
+ # @return [Module::Cluster::InstanceController::HookController] self
158
+ #
159
+ def action( & block )
160
+
161
+ action_at_index( -1, nil, nil, nil, false, & block )
162
+
163
+ return self
164
+
165
+ end
166
+
167
+ ###################
168
+ # before_extend #
169
+ ###################
170
+
171
+ ###
172
+ # Declare that chained actions should be inserted into the event stack prior to the location
173
+ # in the same event stack where provided module(s) are specified to be extended.
174
+ #
175
+ # @overload before_extend( module, ..., & block )
176
+ #
177
+ # @param module Module that insert should be prior to.
178
+ #
179
+ # @yield [hooked_instance] Block for event hook action.
180
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
181
+ # Equivalent to parameter for #included and #extended.
182
+ #
183
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
184
+ #
185
+ def before_extend( *modules, & block )
186
+
187
+ before_module_index = lowest_index( :extend, *modules )
188
+
189
+ proxy = chain_proxy
190
+
191
+ proxy.index( before_module_index )
192
+
193
+ if block_given?
194
+ proxy.action( & block )
195
+ end
196
+
197
+ return proxy
198
+
199
+ end
200
+
201
+ ####################
202
+ # before_include #
203
+ ####################
204
+
205
+ ###
206
+ # Declare that chained actions should be inserted into the event stack prior to the location
207
+ # in the same event stack where provided module(s) are specified to be included.
208
+ #
209
+ # @overload before_include( module, ..., & block )
210
+ #
211
+ # @param module Module that insert should be prior to.
212
+ #
213
+ # @yield [hooked_instance] Block for event hook action.
214
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
215
+ # Equivalent to parameter for #included and #extended.
216
+ #
217
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
218
+ #
219
+ def before_include( *modules, & block )
220
+
221
+ before_module_index = lowest_index( :include, *modules )
222
+
223
+ proxy = chain_proxy
224
+
225
+ proxy.index( before_module_index )
226
+
227
+ if block_given?
228
+ proxy.action( & block )
229
+ end
230
+
231
+ return proxy
232
+
233
+ end
234
+
235
+ ##############################
236
+ # before_include_or_extend #
237
+ # before_extend_or_include #
238
+ ##############################
239
+
240
+ ###
241
+ # Declare that chained actions should be inserted into the event stack prior to the location
242
+ # in the same event stack where provided module(s) are specified to be included or extended.
243
+ #
244
+ # @overload before_include_or_extend( module, ..., & block )
245
+ #
246
+ # @param module Module that insert should be prior to.
247
+ #
248
+ # @yield [hooked_instance] Block for event hook action.
249
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
250
+ # Equivalent to parameter for #included and #extended.
251
+ #
252
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
253
+ #
254
+ def before_include_or_extend( *modules, & block )
255
+
256
+ before_module_index = lowest_index( :include_or_extend, *modules )
257
+
258
+ proxy = chain_proxy
259
+
260
+ proxy.index( before_module_index )
261
+
262
+ if block_given?
263
+ proxy.action( & block )
264
+ end
265
+
266
+ return proxy
267
+
268
+ end
269
+
270
+ alias_method :before_extend_or_include, :before_include_or_extend
271
+
272
+ ###################
273
+ # after_include #
274
+ ###################
275
+
276
+ ###
277
+ # Declare that chained actions should be inserted into the event stack after the location
278
+ # in the same event stack where provided module(s) are specified to be included.
279
+ #
280
+ # @overload before_include( module, ..., & block )
281
+ #
282
+ # @param module Module that insert should be after.
283
+ #
284
+ # @yield [hooked_instance] Block for event hook action.
285
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
286
+ # Equivalent to parameter for #included and #extended.
287
+ #
288
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
289
+ #
290
+ def after_include( *modules, & block )
291
+
292
+ after_module_index = highest_index( :include, *modules ) + 1
293
+
294
+ proxy = chain_proxy
295
+
296
+ proxy.index( after_module_index )
297
+
298
+ if block_given?
299
+ proxy.action( & block )
300
+ end
301
+
302
+ return proxy
303
+
304
+ end
305
+
306
+ ##################
307
+ # after_extend #
308
+ ##################
309
+
310
+ ###
311
+ # Declare that chained actions should be inserted into the event stack after the location
312
+ # in the same event stack where provided module(s) are specified to be extended.
313
+ #
314
+ # @overload before_extend( module, ..., & block )
315
+ #
316
+ # @param module Module that insert should be after.
317
+ #
318
+ # @yield [hooked_instance] Block for event hook action.
319
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
320
+ # Equivalent to parameter for #included and #extended.
321
+ #
322
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
323
+ #
324
+ def after_extend( *modules, & block )
325
+
326
+ after_module_index = highest_index( :extend, *modules ) + 1
327
+
328
+ proxy = chain_proxy
329
+
330
+ proxy.index( after_module_index )
331
+
332
+ if block_given?
333
+ proxy.action( & block )
334
+ end
335
+
336
+ return proxy
337
+
338
+ end
339
+
340
+ #############################
341
+ # after_include_or_extend #
342
+ # after_extend_or_include #
343
+ #############################
344
+
345
+ ###
346
+ # Declare that chained actions should be inserted into the event stack after the location
347
+ # in the same event stack where provided module(s) are specified to be included or extended.
348
+ #
349
+ # @overload before_include_or_extend( module, ..., & block )
350
+ #
351
+ # @param module Module that insert should be after.
352
+ #
353
+ # @yield [hooked_instance] Block for event hook action.
354
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
355
+ # Equivalent to parameter for #included and #extended.
356
+ #
357
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy for chained declarations.
358
+ #
359
+ def after_include_or_extend( *modules, & block )
360
+
361
+ after_module_index = highest_index( :include_or_extend, *modules ) + 1
362
+
363
+ proxy = chain_proxy
364
+
365
+ proxy.index( after_module_index )
366
+
367
+ if block_given?
368
+ proxy.action( & block )
369
+ end
370
+
371
+ return proxy
372
+
373
+ end
374
+
375
+ alias_method :after_extend_or_include, :after_include_or_extend
376
+
377
+ ######################################################################################################################
378
+ # private ##########################################################################################################
379
+ ######################################################################################################################
380
+
381
+ ###
382
+ # These methods are not actually in private space but are internal methods for inter-object
383
+ # communications. They aren't intended for public interfacing.
384
+ #
385
+
386
+ ###########
387
+ # stack #
388
+ ###########
389
+
390
+ ###
391
+ # @private
392
+ #
393
+ # Each hook controller maintains a stack of event hooks to iterate at each include/extend/subclass event.
394
+ #
395
+ # @!attribute [reader] Stack of event hooks.
396
+ #
397
+ # @return [Array] Stack of event hooks.
398
+ #
399
+ attr_reader :stack
400
+
401
+ ##########
402
+ # name #
403
+ ##########
404
+
405
+ ###
406
+ # @private
407
+ #
408
+ # Name of hook controller.
409
+ #
410
+ # @return [Symbol,String] Name.
411
+ #
412
+ attr_reader :name
413
+
414
+ ################################
415
+ # parent_instance_controller #
416
+ ################################
417
+
418
+ ###
419
+ # @private
420
+ #
421
+ # @!attribute [reader] Reference to instance controller for which this hook controller operates.
422
+ #
423
+ # @return [Module::Cluster::InstanceController]
424
+ #
425
+ attr_reader :parent_instance_controller
426
+
427
+ ######################
428
+ # include_at_index #
429
+ ######################
430
+
431
+ ###
432
+ # @private
433
+ #
434
+ # Used by ChainProxy to insert modules before/after other modules.
435
+ #
436
+ # @param index Index where include should occur.
437
+ #
438
+ # @param cluster_name Name of cluster for which include event is to occur.
439
+ #
440
+ # @param contexts Contexts for which event hooks should occur.
441
+ #
442
+ # @param cascade_to Contexts for which event hooks should cascade.
443
+ #
444
+ # @param explicit_set Whether insert is an implicit position or an explicitly requested position.
445
+ #
446
+ # @param modules Modules to include.
447
+ #
448
+ # @yield [hooked_instance] Block for event hook action.
449
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
450
+ # Equivalent to parameter for #included and #extended.
451
+ #
452
+ # @return [Integer] Index after inserts.
453
+ #
454
+ def include_at_index( index, cluster_name, contexts, cascade_to, explicit_set = false, *modules, & block )
455
+
456
+ modules.each do |this_module|
457
+
458
+ should_insert = true
459
+
460
+ if @include_modules.has_key?( this_module )
461
+
462
+ if explicit_set
463
+ # if we have an existing index, insert at this one instead
464
+ existing_index = @stack.index { |this_frame | this_frame.action == :include and
465
+ this_frame.module == this_module }
466
+ @stack.delete_at( existing_index )
467
+ if existing_index < index
468
+ index -= 1
469
+ end
470
+ else
471
+ should_insert = false
472
+ end
473
+
474
+ end
475
+
476
+ if should_insert
477
+ this_stack_frame = self.class::FrameStruct.new( @instance,
478
+ cluster_name,
479
+ contexts ? contexts.empty? ? nil : contexts.dup : nil,
480
+ cascade_to ? cascade_to.empty? ? nil : cascade_to.dup : nil,
481
+ block,
482
+ this_module,
483
+ :include )
484
+ @stack.insert( index, this_stack_frame )
485
+ unless index < 0
486
+ index += 1
487
+ end
488
+ @include_modules[ this_module ] = true
489
+ end
490
+
491
+ end
492
+
493
+ return index
494
+
495
+ end
496
+
497
+ #####################
498
+ # extend_at_index #
499
+ #####################
500
+
501
+ ###
502
+ # @private
503
+ #
504
+ # Used by ChainProxy to insert modules before/after other modules.
505
+ #
506
+ # @param index Index where extend should occur.
507
+ #
508
+ # @param cluster_name Name of cluster for which extend event is to occur.
509
+ #
510
+ # @param contexts Contexts for which event hooks should occur.
511
+ #
512
+ # @param cascade_to Contexts for which event hooks should cascade.
513
+ #
514
+ # @param explicit_set Whether insert is an implicit position or an explicitly requested position.
515
+ #
516
+ # @param modules Modules to extend.
517
+ #
518
+ # @yield [hooked_instance] Block for event hook action.
519
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
520
+ # Equivalent to parameter for #extendd and #extended.
521
+ #
522
+ # @return [Integer] Index after inserts.
523
+ #
524
+ def extend_at_index( index, cluster_name, contexts, cascade_to, explicit_set = false, *modules, & block )
525
+
526
+ modules.each do |this_module|
527
+
528
+ should_insert = true
529
+
530
+ if @extend_modules.has_key?( this_module )
531
+
532
+ if explicit_set
533
+ # if we have an existing index, insert at this one instead
534
+ existing_index = @stack.index { |this_frame | this_frame.action == :extend and
535
+ this_frame.module == this_module }
536
+ @stack.delete_at( existing_index )
537
+ if index > 0 and existing_index < index
538
+ index -= 1
539
+ end
540
+ else
541
+ should_insert = false
542
+ end
543
+
544
+ end
545
+
546
+ if should_insert
547
+ this_stack_frame = self.class::FrameStruct.new( @instance,
548
+ cluster_name,
549
+ contexts ? contexts.empty? ? nil : contexts.dup : nil,
550
+ cascade_to ? cascade_to.empty? ? nil : cascade_to.dup : nil,
551
+ block,
552
+ this_module,
553
+ :extend )
554
+ @stack.insert( index, this_stack_frame )
555
+ unless index < 0
556
+ index += 1
557
+ end
558
+ @extend_modules[ this_module ] = true
559
+ end
560
+
561
+ end
562
+
563
+ return index
564
+
565
+ end
566
+
567
+ #################################
568
+ # include_and_extend_at_index #
569
+ #################################
570
+
571
+ ###
572
+ # @private
573
+ #
574
+ # Used by ChainProxy to insert modules before/after other modules.
575
+ #
576
+ # @param index Index where include and extend should occur.
577
+ #
578
+ # @param cluster_name Name of cluster for which include and extend event is to occur.
579
+ #
580
+ # @param contexts Contexts for which event hooks should occur.
581
+ #
582
+ # @param cascade_to Contexts for which event hooks should cascade.
583
+ #
584
+ # @param explicit_set Whether insert is an implicit position or an explicitly requested position.
585
+ #
586
+ # @param modules Modules to include and extend.
587
+ #
588
+ # @yield [hooked_instance] Block for event hook action.
589
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
590
+ # Equivalent to parameter for #include and extendd and #extended.
591
+ #
592
+ # @return [Integer] Index after inserts.
593
+ #
594
+ def include_and_extend_at_index( index, cluster_name, contexts, cascade_to, explicit_set = false, *modules, & block )
595
+
596
+ modules.each do |this_module|
597
+ index = include_at_index( index, cluster_name, contexts, cascade_to, explicit_set, this_module, & block )
598
+ index = extend_at_index( index, cluster_name, contexts, cascade_to, explicit_set, this_module, & block )
599
+ end
600
+
601
+ return index
602
+
603
+ end
604
+
605
+ #################################
606
+ # extend_and_include_at_index #
607
+ #################################
608
+
609
+ ###
610
+ # @private
611
+ #
612
+ # Used by ChainProxy to insert modules before/after other modules.
613
+ #
614
+ # @param index Index where extend and include and extend should occur.
615
+ #
616
+ # @param cluster_name Name of cluster for which extend and include and extend event is to occur.
617
+ #
618
+ # @param contexts Contexts for which event hooks should occur.
619
+ #
620
+ # @param cascade_to Contexts for which event hooks should cascade.
621
+ #
622
+ # @param explicit_set Whether insert is an implicit position or an explicitly requested position.
623
+ #
624
+ # @param modules Modules to extend and include.
625
+ #
626
+ # @yield [hooked_instance] Block for event hook action.
627
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
628
+ # Equivalent to parameter for #extend and include and extendd and #extended.
629
+ #
630
+ # @return [Integer] Index after inserts.
631
+ #
632
+ def extend_and_include_at_index( index, cluster_name, contexts, cascade_to, explicit_set = false, *modules, & block )
633
+
634
+ modules.each do |this_module|
635
+ extend_at_index( index, cluster_name, contexts, cascade_to, explicit_set, this_module, & block )
636
+ include_at_index( index, cluster_name, contexts, cascade_to, explicit_set, this_module, & block )
637
+ end
638
+
639
+ return self
640
+
641
+ end
642
+
643
+ #####################
644
+ # action_at_index #
645
+ #####################
646
+
647
+ ###
648
+ # @private
649
+ #
650
+ # Used by ChainProxy to insert modules before/after other modules.
651
+ #
652
+ # @param index Index where include should occur.
653
+ #
654
+ # @param cluster_name Name of cluster for which include event is to occur.
655
+ #
656
+ # @param contexts Contexts for which event hooks should occur.
657
+ #
658
+ # @param cascade_to Contexts for which event hooks should cascade.
659
+ #
660
+ # @param explicit_set Whether insert is an implicit position or an explicitly requested position.
661
+ #
662
+ # @yield [hooked_instance] Block for event hook action.
663
+ # @yieldparam hooked_instance Instance for which event hook is occurring.
664
+ # Equivalent to parameter for #included and #extended.
665
+ #
666
+ # @return [Integer] Index after inserts.
667
+ #
668
+ def action_at_index( index, cluster_name, contexts, cascade_to, explicit_set = false, & block )
669
+
670
+ new_frame = self.class::FrameStruct.new( @instance, cluster_name, contexts, cascade_to, block )
671
+
672
+ @stack.insert( index, new_frame )
673
+
674
+ unless index < 0
675
+ index += 1
676
+ end
677
+
678
+ return index
679
+
680
+ end
681
+
682
+ #################
683
+ # chain_proxy #
684
+ #################
685
+
686
+ ###
687
+ # @private
688
+ #
689
+ # Get Chain Proxy instance used by this Hook Controller.
690
+ #
691
+ # @return [Module::Cluster::InstanceController::HookController::ChainProxy] Chain Proxy instance.
692
+ #
693
+ def chain_proxy
694
+
695
+ @chain_proxy ||= self.class::ChainProxy.new( self )
696
+
697
+ return @chain_proxy.reset_state
698
+
699
+ end
700
+
701
+ ##################
702
+ # lowest_index #
703
+ ##################
704
+
705
+ ###
706
+ # @private
707
+ #
708
+ # Determine the lowest index for provided module(s).
709
+ #
710
+ # @overload lowest_index( include_or_extend, module, ... )
711
+ #
712
+ # @param include_or_extend :include, :extend or :include_and_extend
713
+ #
714
+ # @param module Modules for which lowest-index is being determined.
715
+ #
716
+ # @return [Integer] Lowest index.
717
+ #
718
+ def lowest_index( include_or_extend, *modules )
719
+
720
+ return indexes( include_or_extend, *modules )[ 0 ]
721
+
722
+ end
723
+
724
+ ###################
725
+ # highest_index #
726
+ ###################
727
+
728
+ ###
729
+ # @private
730
+ #
731
+ # Determine the highest index for provided module(s).
732
+ #
733
+ # @overload highest_index( include_or_extend, module, ... )
734
+ #
735
+ # @param include_or_extend :include, :extend or :include_and_extend
736
+ #
737
+ # @param module Modules for which highest-index is being determined.
738
+ #
739
+ # @return [Integer] Highest index.
740
+ #
741
+ def highest_index( include_or_extend, *modules )
742
+
743
+ return indexes( include_or_extend, *modules )[ -1 ]
744
+
745
+ end
746
+
747
+ ######################################################################################################################
748
+ private ##########################################################################################################
749
+ ######################################################################################################################
750
+
751
+ #############
752
+ # indexes #
753
+ #############
754
+
755
+ ###
756
+ # @private
757
+ #
758
+ # Get indexes for provided module(s).
759
+ #
760
+ # @overload indexes( include_or_extend, module, ... )
761
+ #
762
+ # @param include_or_extend :include, :extend or :include_and_extend
763
+ #
764
+ # @param module Modules for which indexes are being determined.
765
+ #
766
+ # @return [Array<Integer>] Indexes for modules in stack.
767
+ #
768
+ def indexes( include_or_extend, *modules )
769
+
770
+ indexes = [ ]
771
+
772
+ proc = nil
773
+
774
+ modules.each do |this_module|
775
+
776
+ case include_or_extend
777
+ when :include
778
+
779
+ this_index = @stack.index do |this_stack_frame|
780
+ this_stack_frame.action == :include and
781
+ this_stack_frame.module == this_module
782
+ end
783
+
784
+ when :extend
785
+ this_index = @stack.index do |this_stack_frame|
786
+ this_stack_frame.action == :extend and
787
+ this_stack_frame.module == this_module
788
+ end
789
+ when :include_or_extend
790
+ matched_action = nil
791
+ this_index = @stack.index do |this_stack_frame|
792
+ if this_stack_frame.action == :extend || this_stack_frame.action == :include and
793
+ this_stack_frame.module == this_module
794
+ matched_action = this_stack_frame.action
795
+ true
796
+ end
797
+ end
798
+ if this_index
799
+ match_action = nil
800
+ case matched_action
801
+ when :include
802
+ match_action = :extend
803
+ when :extend
804
+ match_action = :include
805
+ end
806
+ # if we matched include or extend look for the other one from the other side
807
+ second_index = @stack.rindex do |this_stack_frame|
808
+ this_stack_frame.action == match_action and
809
+ this_stack_frame.module == this_module
810
+ end
811
+ if second_index and second_index != this_index
812
+ indexes.push( this_index )
813
+ this_index = second_index
814
+ end
815
+ end
816
+ end
817
+
818
+ unless this_index
819
+ raise ::Module::Cluster::Exception::ModuleNotInStack.new( self, this_module )
820
+ end
821
+
822
+ indexes.push( this_index )
823
+
824
+ end
825
+
826
+ return indexes.sort
827
+
828
+ end
829
+
830
+ end