Mercurial > pub > Impl
annotate lib/IMPL/Config/Bag.pm @ 427:09e0086a82a7 ref20150831 tip
Merge
author | cin |
---|---|
date | Tue, 15 May 2018 00:51:33 +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; |