annotate lib/IMPL/Config/Bag.pm @ 414:ec6f2d389d1e ref20150831

working on IMPL::Config::Bag
author cin
date Fri, 02 Oct 2015 06:56:24 +0300
parents af8d359ee4cc
children 3d24b10dd0d5
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
412
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
1 package IMPL::Config::Bag;
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
2 use strict;
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
3
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
4 use IMPL::lang qw(:base);
412
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
5 use IMPL::declare {
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
6 base => [
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
7 'IMPL::Object' => undef
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
8 ],
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
9 props => [
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
10 _parents => '*rw', # array of parent bags
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
11 _state => '*rw', #array of previous timestamps
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
12 _cache => '*rw', # own or cached entries
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
13 _timestamp => '*rw',
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
14 _entries => '*rw', # each entry is represented by hash
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
15 # { isa => linear_isa_hash, owner => owner_of_the_entry, value => value }
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
16 ]
412
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
17 };
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
18
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
19 sub CTOR {
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
20 my ( $this, $p ) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
21
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
22 if ($p) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
23 my @parents;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
24 push @parents, @{ $p->{$_parents} } if $p->{$_parents};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
25 push @parents, $p;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
26 $this->{$_parents} = \@parents;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
27 $this->{$_state} = [ map $_->{$_timestamp}, @parents ];
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
28 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
29
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
30 $this->{$_timestamp} = 0;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
31 $this->{$_cache} = {};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
32 $this->{$_entries} = [];
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
33 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
34
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
35 sub GetParent {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
36 $_[0]->{$_parents} && $_[0]->{$_parents}[0];
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
37 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
38
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
39 sub _Validate {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
40 my ($this) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
41
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
42 my $parents = $this->{$_parents}
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
43 or return;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
44 my $state = $this->{$_state};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
45 my $len = @$parents;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
46 my $flush;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
47
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
48 for ( my $i = 0 ; $i < $len ; $i++ ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
49 if ($flush) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
50 $parents->[$i]{$_cache} = {};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
51 $state->[$i] = $parents->[$i]{$_timestamp};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
52 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
53 else {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
54 $flush = ( $parents->[$i]{$_timestamp} != $state->[$i] );
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
55 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
56 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
57
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
58 if ($flush) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
59 $this->{$_cache} = {};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
60 return 0;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
61 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
62
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
63 return 1;
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
64 }
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
65
412
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
66 sub Resolve {
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
67 my ( $this, $role ) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
68
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
69 if ( my $d = $this->GetDescriptor() ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
70 return $d->{value};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
71 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
72 else {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
73 return;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
74 }
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
75 }
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
76
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
77 sub GetDescriptor {
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
78 my ( $this, $role ) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
79
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
80 my $d = $this->{$_cache}{$role};
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
81
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
82 # return descriptor if this is own descriptor and its level is 1 (i.e. it can't be overriden by the parent cache)
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
83 # otherwise the cache must be validated
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
84 return $d
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
85 if $d
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
86 and ( ( $d->{owner} == $this and $d->{isa}{$role} == 1 )
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
87 or $this->_Validate() );
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
88
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
89 # the cache chain is valid
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
90 # $d is not a valid descriptor
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
91
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
92 $d = undef;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
93 my $prev;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
94
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
95 if ( my $parents = $this->{$_parents} ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
96 foreach my $bag ( @$parents, $this ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
97
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
98 # check the cache;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
99 unless ( my $t = $bag->{$_cache}{$role} ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
100
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
101 # no cached entry this may be due cache flush
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
102 # go through own entries and find better entry than inherited from parents
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
103 foreach my $entry ( @{ $bag->{$_entries} } ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
104 my $level = $entry->{isa}{$role};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
105 if ( $level and ( not($prev) or $level <= $prev ) ) {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
106 $d = $entry;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
107 $prev = $level;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
108 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
109 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
110
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
111 #cache it
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
112 $bag->{$_cache}{$role} = $d if $d;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
113 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
114 else {
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
115 $d = $t;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
116 $prev = $d->{isa}{$role};
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
117 }
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
118 }
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
119 }
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
120
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
121 return $d;
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
122 }
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
123
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
124 sub ResolveAll {
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
125 my ( $this, $role ) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
126
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
127 return [
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
128 map $_->{value},
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
129 grep $_->{isa}{$role},
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
130 map $_->{$_entries},
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
131 @{ $this->{$_parents} || [] },
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
132 $this
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
133 ];
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
134
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
135 }
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
136
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
137 sub Register {
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
138 my ( $this, $isa, $value ) = @_;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
139
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
140 $isa = { $isa, 1 } unless isHash($isa);
413
af8d359ee4cc working on di container
cin
parents: 412
diff changeset
141
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
142 push @{ $this->{$_entries} },
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
143 { owner => $this, isa => $isa, value => $value };
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
144 $this->{$_timestamp}++;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
145
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
146 delete $this->{$_cache}{$_} foreach keys %$isa;
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
147
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
148 return $this;
412
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
149 }
30e8c6a74937 working on di container (role based registrations)
cin
parents:
diff changeset
150
414
ec6f2d389d1e working on IMPL::Config::Bag
cin
parents: 413
diff changeset
151 1;