cascading-configuration-array 1.6.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,52 +1,70 @@
1
1
 
2
- class CascadingConfiguration::Array::CompositingArray < ::Array
3
-
4
- attr_accessor :local_cascading_array
2
+ class ::CascadingConfiguration::Array::CompositingArray < ::Array
5
3
 
6
4
  ################
7
5
  # initialize #
8
6
  ################
9
7
 
10
8
  def initialize( configuration_instance, configuration_name )
11
-
9
+
12
10
  @configuration_instance = configuration_instance
13
-
14
11
  @configuration_name = configuration_name
15
12
 
13
+ # hash tracking index in self corresponding to index in parent
14
+ # this is since objects can be inserted before/between parent objects
15
+ @local_index_for_parent_index = { }
16
+
17
+ # we keep track of how many objects are interpolated between parent objects
18
+ # plus number of parent objects
19
+ @parent_and_interpolated_object_count = 0
20
+ @replaced_parents = {}
21
+
22
+ # arrays that inherit from us
23
+ @sub_composite_arrays = [ ]
24
+
16
25
  # store self for sub composites
17
- ::CascadingConfiguration::Variable.set_configuration_variable( configuration_instance, configuration_name, self )
26
+ ::CascadingConfiguration::Variable.set_configuration_variable( configuration_instance,
27
+ configuration_name,
28
+ self )
18
29
 
19
- # if first ancestor can have a composite array, register self with it in case it gets updated in the future
20
- if ancestor = ::CascadingConfiguration::Variable.ancestor( configuration_instance, configuration_name )
30
+ # if first ancestor can have a composite array, register self with it
31
+ # in case it gets updated in the future
32
+ if ancestor = ::CascadingConfiguration::Variable.ancestor( configuration_instance,
33
+ configuration_name )
34
+
35
+ @super_composite_array = ::CascadingConfiguration::Variable.
36
+ get_configuration_variable( ancestor, configuration_name )
21
37
 
22
- @super_composite_array = ::CascadingConfiguration::Variable.get_configuration_variable( ancestor,
23
- configuration_name )
24
38
  if @super_composite_array.respond_to?( :register_sub_composite_array )
25
39
  @super_composite_array.register_sub_composite_array( self )
40
+ push( *@super_composite_array )
26
41
  else
27
42
  @super_composite_array = nil
28
43
  end
29
-
44
+
45
+ @super_composite_array.count.times do |this_time|
46
+ @local_index_for_parent_index[ this_time ] = this_time
47
+ end
48
+
49
+ # since we have a super array we have to note how many objects it has before we insert any
50
+ @parent_and_interpolated_object_count = @super_composite_array.count
51
+
30
52
  end
31
53
 
32
- # instantiate local cascading array
33
- @local_cascading_array = ::CascadingConfiguration::Array::CompositingArray::LocalConfigurationArray.new
34
-
35
- # we may later have our own child composites that register with us
36
- @sub_composite_arrays = [ ]
37
-
38
- # initialize self status for parent and local
39
- update_self_as_cascading_composite
40
-
41
54
  end
42
55
 
56
+ ################################### Sub-Array Management #######################################
57
+
43
58
  ##################################
44
59
  # register_sub_composite_array #
45
60
  ##################################
46
61
 
47
62
  def register_sub_composite_array( sub_composite_array )
63
+
48
64
  @sub_composite_arrays.push( sub_composite_array )
65
+
49
66
  return self
67
+
50
68
  end
51
69
 
52
70
  ####################################
@@ -54,94 +72,502 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
54
72
  ####################################
55
73
 
56
74
  def unregister_sub_composite_array( sub_composite_array )
75
+
57
76
  @sub_composite_arrays.delete( sub_composite_array )
77
+
58
78
  return self
79
+
59
80
  end
60
81
 
82
+ ##################################### Self Management ##########################################
83
+
61
84
  #########
62
85
  # []= #
63
86
  #########
64
87
 
65
- def []=( index, element )
66
- # we sort internally, so index is irrelevant
67
- # no reason to differentiate from push
68
- push( element )
69
- end
70
-
71
- ########
72
- # << #
73
- ########
88
+ private
89
+ alias_method :non_cascading_set, :[]=
90
+ public
74
91
 
75
- def <<( *elements )
76
- # no reason to differentiate from push
77
- push( *elements )
92
+ def []=( index, object )
93
+
94
+ # we are either replacing or adding at the end
95
+ # if we are replacing we are either replacing a parent element or an element in self
96
+ # * if replacing parent element, track and exclude parent changes
97
+
98
+ non_cascading_set( index, object )
99
+
100
+ if index_inside_parent_objects?( index )
101
+ @replaced_parents[ index ] = true
102
+ end
103
+
104
+ @sub_composite_arrays.each do |this_sub_array|
105
+ this_sub_array.instance_eval do
106
+ update_as_sub_array_for_parent_set( index, object )
107
+ end
108
+ end
109
+
110
+ return object
111
+
78
112
  end
79
113
 
80
- #######
81
- # + #
82
- #######
114
+ ############
115
+ # insert #
116
+ ############
117
+
118
+ private
119
+ alias_method :non_cascading_insert, :insert
120
+ public
121
+
122
+ def insert( index, *objects )
123
+
124
+ # if we have less elements in self than the index we are inserting at
125
+ # we need to make sure the nils inserted cascade
126
+ if index > count
127
+ nils_created = index - count
128
+ index -= nils_created
129
+ nils = [ ]
130
+ nils_created.times do |this_time|
131
+ nils.push( nil )
132
+ end
133
+ objects = nils.concat( objects )
134
+ end
135
+
136
+ non_cascading_insert( index, *objects )
137
+
138
+ if index_inside_parent_objects?( index )
139
+ update_corresponding_index_for_local_change( index, objects.count )
140
+ end
83
141
 
84
- def +( *arrays )
85
- # no reason to differentiate from push
86
- arrays.each do |this_array|
87
- push( *this_array )
142
+ @sub_composite_arrays.each do |this_sub_array|
143
+ this_sub_array.instance_eval do
144
+ update_as_sub_array_for_parent_insert( index, *objects )
145
+ end
88
146
  end
147
+
89
148
  return self
149
+
90
150
  end
91
151
 
152
+ ##########
153
+ # push #
154
+ ##########
155
+
156
+ def push( *objects )
157
+
158
+ insert( count, *objects )
159
+
160
+ return self
161
+
162
+ end
163
+ alias_method :<<, :push
164
+
92
165
  ############
93
166
  # concat #
94
167
  ############
95
168
 
96
169
  def concat( *arrays )
170
+
97
171
  arrays.each do |this_array|
98
172
  push( *this_array )
99
173
  end
174
+
175
+ return self
176
+
100
177
  end
178
+ alias_method :+, :concat
101
179
 
102
- ##########
103
- # push #
104
- ##########
180
+ ############
181
+ # delete #
182
+ ############
105
183
 
106
- alias_method :super_push, :push
107
- def push( *elements )
108
-
109
- # we are a composite array
110
- # that means we have to set the value for our class
111
- @local_cascading_array.push( *elements )
112
-
113
- update_adding_composite_elements( *elements )
184
+ def delete( object )
114
185
 
115
- return self
186
+ return_value = nil
187
+
188
+ if index = index( object )
189
+ return_value = delete_at( index )
190
+ end
191
+
192
+ return return_value
116
193
 
117
194
  end
195
+
196
+ ####################
197
+ # delete_objects #
198
+ ####################
118
199
 
200
+ def delete_objects( *objects )
201
+
202
+ return_value = nil
203
+
204
+ indexes = [ ]
205
+ objects.each do |this_object|
206
+ this_index = index( this_object )
207
+ if this_index
208
+ indexes.push( this_index )
209
+ end
210
+ end
211
+
212
+ unless indexes.empty?
213
+ return_value = delete_at_indexes( *indexes )
214
+ end
215
+
216
+ return return_value
217
+
218
+ end
219
+
119
220
  #######
120
221
  # - #
121
222
  #######
122
-
223
+
123
224
  def -( *arrays )
124
225
 
125
226
  arrays.each do |this_array|
126
- delete( *this_array )
227
+ delete_objects( *this_array )
127
228
  end
128
229
 
129
230
  return self
130
231
 
131
232
  end
132
233
 
133
- ############
134
- # delete #
135
- ############
234
+ ###############
235
+ # delete_at #
236
+ ###############
237
+
238
+ private
239
+ alias_method :non_cascading_delete_at, :delete_at
240
+ public
136
241
 
137
- alias_method :super_delete, :delete
138
- def delete( *elements )
242
+ def delete_at( index )
243
+
244
+ deleted_object = non_cascading_delete_at( index )
245
+
246
+ @replaced_parents.delete( index )
247
+
248
+ if index_inside_parent_objects?( index )
249
+ update_corresponding_index_for_local_change( index, -1 )
250
+ end
251
+
252
+ @sub_composite_arrays.each do |this_sub_array|
253
+ this_sub_array.instance_eval do
254
+ update_as_sub_array_for_parent_delete( index )
255
+ end
256
+ end
257
+
258
+ return deleted_object
259
+
260
+ end
261
+
262
+ #######################
263
+ # delete_at_indexes #
264
+ #######################
265
+
266
+ def delete_at_indexes( *indexes )
267
+
268
+ indexes = indexes.sort.uniq.reverse
269
+
270
+ objects = [ ]
271
+
272
+ indexes.each do |this_index|
273
+ objects.push( delete_at( this_index ) )
274
+ end
275
+
276
+ return objects
277
+
278
+ end
279
+
280
+ ###############
281
+ # delete_if #
282
+ ###############
283
+
284
+ def delete_if
285
+
286
+ return to_enum unless block_given?
287
+
288
+ indexes = [ ]
289
+
290
+ self.each_with_index do |this_object, index|
291
+ if yield( this_object )
292
+ indexes.push( index )
293
+ end
294
+ end
295
+
296
+ delete_at_indexes( *indexes )
297
+
298
+ return self
299
+
300
+ end
139
301
 
140
- @local_cascading_array.delete( *elements )
302
+ #############
303
+ # keep_if #
304
+ #############
305
+
306
+ def keep_if
307
+
308
+ indexes = [ ]
309
+
310
+ self.each_with_index do |this_object, index|
311
+ unless yield( this_object )
312
+ indexes.push( index )
313
+ end
314
+ end
315
+
316
+ delete_at_indexes( *indexes )
317
+
318
+ return self
319
+
320
+ end
321
+
322
+ ##############
323
+ # compact! #
324
+ ##############
325
+
326
+ def compact!
327
+
328
+ return keep_if do |object|
329
+ object != nil
330
+ end
331
+
332
+ end
333
+
334
+ ##############
335
+ # flatten! #
336
+ ##############
337
+
338
+ def flatten!
339
+
340
+ return_value = nil
341
+
342
+ indexes = [ ]
343
+
344
+ self.each_with_index do |this_object, index|
345
+ if this_object.is_a?( Array )
346
+ indexes.push( index )
347
+ end
348
+ end
349
+
350
+ unless indexes.empty?
351
+ indexes.sort!.reverse!
352
+ indexes.each do |this_index|
353
+ this_array = delete_at( this_index )
354
+ insert( this_index, *this_array )
355
+ end
356
+ return_value = self
357
+ end
358
+
359
+ return return_value
360
+
361
+ end
362
+
363
+ #############
364
+ # reject! #
365
+ #############
366
+
367
+ def reject!
368
+
369
+ return to_enum unless block_given?
370
+
371
+ return_value = nil
372
+
373
+ deleted_objects = 0
374
+
375
+ iteration_dup = dup
376
+ iteration_dup.each_with_index do |this_object, index|
377
+ if yield( this_object )
378
+ delete_at( index - deleted_objects )
379
+ deleted_objects += 1
380
+ end
381
+ end
382
+
383
+ if deleted_objects > 0
384
+ return_value = self
385
+ end
386
+
387
+ return return_value
388
+
389
+ end
390
+
391
+ #############
392
+ # replace #
393
+ #############
394
+
395
+ def replace( other_array )
396
+
397
+ clear
398
+
399
+ other_array.each_with_index do |this_object, index|
400
+ unless self[ index ] == this_object
401
+ self[ index ] = this_object
402
+ end
403
+ end
404
+
405
+ return self
406
+
407
+ end
141
408
 
142
- update_removing_composite_elements( *elements )
409
+ ##############
410
+ # reverse! #
411
+ ##############
412
+
413
+ def reverse!
414
+
415
+ reversed_array = reverse
416
+
417
+ clear
418
+
419
+ reversed_array.each_with_index do |this_object, index|
420
+ self[ index ] = this_object
421
+ end
422
+
423
+ return self
424
+
425
+ end
426
+
427
+ #############
428
+ # rotate! #
429
+ #############
430
+
431
+ def rotate!( rotate_count = 1 )
432
+
433
+ reversed_array = rotate( rotate_count )
434
+
435
+ clear
436
+
437
+ reversed_array.each_with_index do |this_object, index|
438
+ self[ index ] = this_object
439
+ end
440
+
441
+ return self
442
+
443
+ end
444
+
445
+ #############
446
+ # select! #
447
+ #############
448
+
449
+ def select!
450
+
451
+ return to_enum unless block_given?
452
+
453
+ deleted_objects = 0
454
+
455
+ iteration_dup = dup
456
+ iteration_dup.each_with_index do |this_object, index|
457
+ unless yield( this_object )
458
+ delete_at( index - deleted_objects )
459
+ deleted_objects += 1
460
+ end
461
+ end
143
462
 
144
463
  return self
464
+
465
+ end
466
+
467
+ ##############
468
+ # shuffle! #
469
+ ##############
470
+
471
+ def shuffle!( random_number_generator = nil )
472
+
473
+ shuffled_array = shuffle( random: random_number_generator )
474
+
475
+ clear
476
+
477
+ shuffled_array.each_with_index do |this_object, index|
478
+ self[ index ] = this_object
479
+ end
480
+
481
+ return self
482
+
483
+ end
484
+
485
+ ##############
486
+ # collect! #
487
+ # map! #
488
+ ##############
489
+
490
+ def collect!
491
+
492
+ return to_enum unless block_given?
493
+
494
+ self.each_with_index do |this_object, index|
495
+ replacement_object = yield( this_object )
496
+ self[ index ] = replacement_object
497
+ end
498
+
499
+ return self
500
+
501
+ end
502
+ alias_method :map!, :collect!
503
+
504
+ ###########
505
+ # sort! #
506
+ ###########
507
+
508
+ def sort!( & block )
509
+
510
+ sorted_array = sort( & block )
511
+
512
+ unless sorted_array == self
513
+
514
+ replace( sorted_array )
515
+
516
+ end
517
+
518
+ return self
519
+
520
+ end
521
+
522
+ ##############
523
+ # sort_by! #
524
+ ##############
525
+
526
+ def sort_by!( & block )
527
+
528
+ return to_enum unless block_given?
529
+
530
+ sorted_array = sort_by( & block )
531
+
532
+ unless sorted_array == self
533
+
534
+ replace( sorted_array )
535
+
536
+ end
537
+
538
+ return self
539
+
540
+ end
541
+
542
+ ###########
543
+ # uniq! #
544
+ ###########
545
+
546
+ def uniq!
547
+
548
+ return_value = nil
549
+
550
+ uniq_array = uniq
551
+
552
+ unless uniq_array == self
553
+
554
+ clear
555
+
556
+ replace( uniq_array )
557
+
558
+ end
559
+
560
+ return return_value
561
+
562
+ end
563
+
564
+ #############
565
+ # unshift #
566
+ #############
567
+
568
+ def unshift( object )
569
+
570
+ insert( 0, object )
145
571
 
146
572
  end
147
573
 
@@ -151,13 +577,9 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
151
577
 
152
578
  def pop
153
579
 
154
- element = super
155
-
156
- @local_cascading_array.delete( element )
157
-
158
- update_removing_composite_elements( element )
580
+ object = delete_at( count - 1 )
159
581
 
160
- return element
582
+ return object
161
583
 
162
584
  end
163
585
 
@@ -167,13 +589,9 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
167
589
 
168
590
  def shift
169
591
 
170
- element = super
171
-
172
- @local_cascading_array.delete( element )
592
+ object = delete_at( 0 )
173
593
 
174
- update_removing_composite_elements( element )
175
-
176
- return element
594
+ return object
177
595
 
178
596
  end
179
597
 
@@ -181,15 +599,43 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
181
599
  # slice! #
182
600
  ############
183
601
 
184
- def slice!( *args )
602
+ def slice!( index_start_or_range, length = nil )
185
603
 
186
- elements = super
604
+ slice = nil
605
+
606
+ start_index = nil
607
+ end_index = nil
608
+
609
+ if index_start_or_range.is_a?( Range )
610
+
611
+ start_index = index_start_or_range.begin
612
+ end_index = index_start_or_range.end
613
+
614
+ elsif length
615
+
616
+ start_index = index_start_or_range
617
+ end_index = index_start_or_range + length
618
+
619
+ end
187
620
 
188
- @local_cascading_array.delete( *elements )
621
+ if end_index
622
+
623
+ indexes = [ ]
624
+
625
+ ( end_index - start_index ).times do |this_time|
626
+ indexes.push( end_index - this_time - 1 )
627
+ end
189
628
 
190
- update_removing_composite_elements( *elements )
191
-
192
- return elements
629
+ slice = delete_at_indexes( *indexes )
630
+
631
+ else
632
+
633
+ slice = delete_at( start_index )
634
+
635
+ end
636
+
637
+
638
+ return slice
193
639
 
194
640
  end
195
641
 
@@ -197,13 +643,15 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
197
643
  # clear #
198
644
  ###########
199
645
 
200
- alias_method :super_clear, :clear
201
646
  def clear
202
647
 
203
- # add all existing values to exclude array
204
- @local_cascading_array.delete( *self )
648
+ indexes = [ ]
649
+
650
+ count.times do |this_time|
651
+ indexes.push( count - this_time - 1 )
652
+ end
205
653
 
206
- update_removing_composite_elements( *self )
654
+ delete_at_indexes( *indexes )
207
655
 
208
656
  return self
209
657
 
@@ -216,69 +664,197 @@ class CascadingConfiguration::Array::CompositingArray < ::Array
216
664
  # freezes configuration and prevents ancestors from changing this configuration in the future
217
665
  def freeze!
218
666
 
219
- # move current configuration into local configuration
220
- @local_cascading_array.clear
221
- @local_cascading_array.exclude_array.clear
222
- @local_cascading_array.push( *self )
223
-
224
667
  # unregister with parent composite so we don't get future updates from it
225
- @super_composite_array.unregister_sub_composite_array( self ) if @super_composite_array
668
+ if @super_composite_array
669
+ @super_composite_array.unregister_sub_composite_array( self )
670
+ end
226
671
 
227
672
  return self
228
673
 
229
674
  end
230
675
 
231
- ###########################################################################################################
232
- private ###############################################################################################
233
- ###########################################################################################################
676
+ ##################################################################################################
677
+ private ######################################################################################
678
+ ##################################################################################################
234
679
 
235
- ########################################
236
- # update_self_as_cascading_composite #
237
- ########################################
680
+ ################ Self Management for Inserts between Parent-Provided Elements ##################
238
681
 
239
- def update_self_as_cascading_composite
240
- # start fresh
241
- super_clear
242
- # add parent config
243
- super_push( *@super_composite_array ) if @super_composite_array
244
- # add additional local config
245
- super_push( *@local_cascading_array )
246
- # remove local exclude
247
- super_delete( *@local_cascading_array.exclude_array ) unless @local_cascading_array.exclude_array.empty?
248
- # notify children to update their composite status
249
- update_sub_composite_arrays
250
- return self
682
+ ###################################
683
+ # index_inside_parent_objects? #
684
+ ###################################
685
+
686
+ def index_inside_parent_objects?( index )
687
+
688
+ index_inside_parent_objects = false
689
+
690
+ if index < @parent_and_interpolated_object_count
691
+
692
+ index_inside_parent_objects = true
693
+
694
+ end
695
+
696
+ return index_inside_parent_objects
697
+
251
698
  end
252
699
 
253
- ######################################
254
- # update_adding_composite_elements #
255
- ######################################
700
+ #################################################
701
+ # update_corresponding_index_for_local_change #
702
+ #################################################
703
+
704
+ def update_corresponding_index_for_local_change( index, step_value )
705
+
706
+ # update corresponding indexes for changes in self
707
+
708
+ indexes_to_delete = [ ]
709
+
710
+ @local_index_for_parent_index.each do |this_parent_index, this_local_index|
711
+ if this_parent_index >= index
712
+ existing_corresponding_value = @local_index_for_parent_index[ this_parent_index ]
713
+ new_corresponding_value = existing_corresponding_value + step_value
714
+ if new_corresponding_value >= 0
715
+ @local_index_for_parent_index[ this_parent_index ] = new_corresponding_value
716
+ else
717
+ indexes_to_delete.push( this_parent_index )
718
+ end
719
+ end
720
+ end
256
721
 
257
- def update_adding_composite_elements( *elements_to_cascade )
258
- super_push( *elements_to_cascade )
259
- sort!.uniq!
260
- update_sub_composite_arrays
722
+ step_parent_and_interpolated_object_count( step_value )
723
+
261
724
  end
262
725
 
726
+ ######################### Self-as-Sub Management for Parent Updates ############################
727
+
263
728
  ########################################
264
- # update_removing_composite_elements #
729
+ # update_as_sub_array_for_parent_set #
265
730
  ########################################
731
+
732
+ def update_as_sub_array_for_parent_set( index, object )
733
+
734
+ # if our index is bigger than current parent set we are inserting
735
+ if index >= @parent_and_interpolated_object_count
736
+
737
+ update_as_sub_array_for_parent_insert( index, object )
738
+
739
+ # otherwise we are replacing and have a corresponding element defined already
740
+ else
266
741
 
267
- def update_removing_composite_elements( *elements_to_exclude )
268
- elements_to_exclude.each do |this_excluded_element|
269
- super_delete( this_excluded_element )
742
+ unless @replaced_parents[ index ]
743
+
744
+ corresponding_index = @local_index_for_parent_index[ index ]
745
+ non_cascading_set( corresponding_index, object )
746
+
747
+ @sub_composite_arrays.each do |this_array|
748
+ this_array.instance_eval do
749
+ update_as_sub_array_for_parent_set( corresponding_index, object )
750
+ end
751
+ end
752
+
753
+ end
754
+
270
755
  end
271
- update_sub_composite_arrays
756
+
272
757
  end
273
758
 
274
- ###################################
275
- # update_sub_composite_arrays #
276
- ###################################
759
+ ###########################################
760
+ # update_as_sub_array_for_parent_insert #
761
+ ###########################################
762
+
763
+ def update_as_sub_array_for_parent_insert( index, *objects )
764
+
765
+ # new parent indexes have been inserted at index in parent
766
+
767
+ # we need the corresponding index in self where parallel insert will occur
768
+ if corresponding_index = @local_index_for_parent_index[ index ]
769
+
770
+ if corresponding_index < 0
771
+ corresponding_index = 0
772
+ else
773
+ update_corresponding_index_for_parent_change( index, objects.count )
774
+ end
775
+
776
+ else
777
+
778
+ corresponding_index = @parent_and_interpolated_object_count
779
+ @parent_and_interpolated_object_count += objects.count
780
+
781
+ end
782
+
783
+ # then we're going to increment existing correspondences
784
+ # now since we added a space for the new elements we can add their new correspondences
785
+ objects.count.times do |this_time|
786
+ new_parent_index = index + this_time
787
+ new_corresponding_index = corresponding_index + this_time
788
+ @local_index_for_parent_index[ new_parent_index ] = new_corresponding_index
789
+ end
790
+
791
+ non_cascading_insert( corresponding_index, *objects )
792
+
793
+ @sub_composite_arrays.each do |this_array|
794
+ this_array.instance_eval do
795
+ update_as_sub_array_for_parent_insert( corresponding_index, *objects )
796
+ end
797
+ end
798
+
799
+ end
277
800
 
278
- def update_sub_composite_arrays
279
- @sub_composite_arrays.each do |this_composite_array|
280
- this_composite_array.instance_eval { update_self_as_cascading_composite }
801
+ ###########################################
802
+ # update_as_sub_array_for_parent_delete #
803
+ ###########################################
804
+
805
+ def update_as_sub_array_for_parent_delete( index )
806
+
807
+ corresponding_index = @local_index_for_parent_index[ index ]
808
+
809
+ object = non_cascading_delete_at( corresponding_index )
810
+
811
+ @parent_and_interpolated_object_count -= 1
812
+
813
+ @sub_composite_arrays.each do |this_array|
814
+ this_array.instance_eval do
815
+ update_as_sub_array_for_parent_delete( corresponding_index )
816
+ end
817
+ end
818
+
819
+ end
820
+
821
+ ##################################################
822
+ # update_corresponding_index_for_parent_change #
823
+ ##################################################
824
+
825
+ def update_corresponding_index_for_parent_change( parent_index, step_value )
826
+
827
+ # update corresponding indexes for changes in parent
828
+
829
+ stepped_indices = { }
830
+
831
+ # iterate the hash with all indices included and increment/decrement any >= parent_index
832
+ @local_index_for_parent_index.each do |this_parent_index, this_local_index|
833
+ if this_parent_index >= parent_index
834
+ new_index = this_parent_index + step_value
835
+ stepped_indices[ new_index ] = @local_index_for_parent_index.delete( this_parent_index ) + step_value
836
+ end
281
837
  end
838
+
839
+ # merge stepped indices back in
840
+ @local_index_for_parent_index.merge!( stepped_indices )
841
+
842
+ step_parent_and_interpolated_object_count( step_value )
843
+
282
844
  end
283
845
 
846
+ ###############################################
847
+ # step_parent_and_interpolated_object_count #
848
+ ###############################################
849
+
850
+ def step_parent_and_interpolated_object_count( step_value )
851
+
852
+ @parent_and_interpolated_object_count += step_value
853
+
854
+ if @parent_and_interpolated_object_count < 0
855
+ @parent_and_interpolated_object_count = 0
856
+ end
857
+
858
+ end
859
+
284
860
  end