Mercurial > pub > Impl
annotate lib/IMPL/Config/Bag.pm @ 425:c27434cdd611 ref20150831
sync
| author | cin |
|---|---|
| date | Tue, 03 Apr 2018 19:30:01 +0300 |
| parents | b0481c071bea |
| children |
| rev | line source |
|---|---|
| 412 | 1 package IMPL::Config::Bag; |
| 2 use strict; | |
| 3 | |
| 414 | 4 use IMPL::lang qw(:base); |
| 412 | 5 use IMPL::declare { |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
6 base => [ |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
7 'IMPL::Object' => undef |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
8 ], |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
9 props => [ |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
10 _parents => '*rw', # array of parent bags |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
11 _parentRev => '*rw', # the timestamp of the parent |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
12 _sealed => '*rw', # the bag has descendants |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
13 _cache => '*rw', # own or cached entries |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
14 _timestamp => '*rw', |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
15 _entries => '*rw', # each entry is represented by hash |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
16 # { isa => linear_isa_hash, owner => owner_of_the_entry, value => value } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
17 tag => 'rw' # used to store additional information |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
18 ] |
| 412 | 19 }; |
| 20 | |
| 413 | 21 sub CTOR { |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
22 my ( $this, $p ) = @_; |
| 414 | 23 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
24 if ($p) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
25 $p->_Seal(); |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
26 my @parents; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
27 push @parents, @{ $p->{$_parents} } if $p->{$_parents}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
28 push @parents, $p; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
29 $this->{$_parents} = \@parents; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
30 $this->{$_parentRev} = $p->{$_timestamp}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
31 } |
| 414 | 32 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
33 $this->{$_timestamp} = 0; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
34 $this->{$_cache} = {}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
35 $this->{$_entries} = []; |
| 414 | 36 } |
| 37 | |
| 38 sub GetParent { | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
39 my ($this) = @_; |
| 415 | 40 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
41 $this->{$_parents} && $this->{$_parents}[ @{ $this->{$_parents} } - 1 ]; |
| 415 | 42 } |
| 43 | |
| 44 sub _Seal { | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
45 unless ( $_[0]->{$_sealed} ) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
46 $_[0]->{$_sealed} = 1; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
47 $_[0]->{$_timestamp} = 0; # from now the timestamp is important |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
48 } |
| 414 | 49 } |
| 50 | |
| 51 sub _Validate { | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
52 my ($this) = @_; |
| 414 | 53 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
54 my $chain = $this->{$_parents} |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
55 or return 1; |
| 414 | 56 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
57 my $rev = 0; # rev 0 means that parent was never modified |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
58 # this allows to made more efficient checks |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
59 my $flush; |
| 417 | 60 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
61 foreach my $bag ( @$chain, $this ) { |
| 417 | 62 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
63 # we need to updated all bags after the first change was detected; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
64 if ( $flush ||= $rev and $bag->{$_parentRev} != $rev ) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
65 $bag->{$_cache} = {}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
66 $bag->{$_parentRev} = $rev; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
67 } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
68 $rev = $bag->{$_timestamp}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
69 } |
| 417 | 70 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
71 return $flush ? 0 : 1; |
| 413 | 72 } |
| 73 | |
| 412 | 74 sub Resolve { |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
75 my ( $this, $role ) = @_; |
| 414 | 76 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
77 die IMPL::InvalidArgumentException->new('role') |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
78 unless defined $role; |
| 415 | 79 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
80 if ( my $d = $this->_GetDescriptor($role) ) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
81 return wantarray ? @{$d}{'value', 'owner'} : $d->{value}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
82 } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
83 else { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
84 return; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
85 } |
| 413 | 86 } |
| 87 | |
| 415 | 88 sub _GetDescriptor { |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
89 my ( $this, $role ) = @_; |
| 414 | 90 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
91 my $d = $this->{$_cache}{$role}; |
| 414 | 92 |
| 93 # return descriptor if this is own descriptor and its level is 1 (i.e. it can't be overriden by the parent cache) | |
| 94 # otherwise the cache must be validated | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
95 return $d |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
96 if $d |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
97 and ( ( $d->{owner} == $this and $d->{isa}{$role} == 1 ) |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
98 or $this->_Validate() ); |
| 414 | 99 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
100 # if there were no descriptor in cache we need to ensure that the cache |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
101 # chain is valid before reolving starts |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
102 $this->_Validate() unless $d; |
| 415 | 103 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
104 # the cache chain is valid |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
105 # $d is not a valid descriptor |
| 414 | 106 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
107 $d = undef; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
108 my $prev; |
| 414 | 109 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
110 my $parents = $this->{$_parents}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
111 my @bags = $parents ? ( @$parents, $this ) : ($this); |
| 414 | 112 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
113 foreach my $bag (@bags) { |
| 417 | 114 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
115 # check the cache; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
116 unless ( my $t = $bag->{$_cache}{$role} ) { |
| 414 | 117 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
118 # no cached entry this may be due cache flush |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
119 # go through own entries and find better entry than inherited from parents |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
120 foreach my $entry ( @{ $bag->{$_entries} } ) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
121 my $level = $entry->{isa}{$role}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
122 if ( $level and ( not($prev) or $level <= $prev ) ) { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
123 $d = $entry; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
124 $prev = $level; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
125 } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
126 } |
| 414 | 127 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
128 #cache it |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
129 $bag->{$_cache}{$role} = $d if $d; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
130 } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
131 else { |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
132 $d = $t; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
133 $prev = $d->{isa}{$role}; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
134 } |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
135 } |
| 414 | 136 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
137 return $d; |
| 413 | 138 } |
| 139 | |
| 140 sub ResolveAll { | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
141 my ( $this, $role ) = @_; |
| 414 | 142 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
143 return [ |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
144 map $_->{value}, |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
145 grep $_->{isa}{$role}, |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
146 map @{ $_->{$_entries} }, |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
147 @{ $this->{$_parents} || [] }, |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
148 $this |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
149 ]; |
| 414 | 150 |
| 413 | 151 } |
| 152 | |
| 153 sub Register { | |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
154 my ( $this, $isa, $value ) = @_; |
| 414 | 155 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
156 $isa = { $isa, 1 } unless ishash($isa); |
| 413 | 157 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
158 push @{ $this->{$_entries} }, |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
159 { owner => $this, isa => $isa, value => $value }; |
|
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
160 $this->{$_timestamp}++; |
| 414 | 161 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
162 delete $this->{$_cache}{$_} foreach keys %$isa; |
| 414 | 163 |
|
422
b0481c071bea
IMPL::Config::Container tests, YAMLConfiguration now works and tested
cin
parents:
417
diff
changeset
|
164 return $this; |
| 412 | 165 } |
| 166 | |
| 414 | 167 1; |
