line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bolts::Injector; |
2
|
|
|
|
|
|
|
$Bolts::Injector::VERSION = '0.142930'; |
3
|
|
|
|
|
|
|
# ABSTRACT: inject options and parameters into artifacts |
4
|
|
|
|
|
|
|
|
5
|
8
|
|
|
8
|
|
3809
|
use Moose::Role; |
|
8
|
|
|
|
|
14
|
|
|
8
|
|
|
|
|
71
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
our @CARP_NOT = qw( |
8
|
|
|
|
|
|
|
Bolts::Injector::Parameter::ByName |
9
|
|
|
|
|
|
|
Bolts::Artifact |
10
|
|
|
|
|
|
|
); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
has init_locator => ( |
14
|
|
|
|
|
|
|
is => 'ro', |
15
|
|
|
|
|
|
|
isa => 'Bolts::Role::Locator', |
16
|
|
|
|
|
|
|
weak_ref => 1, |
17
|
|
|
|
|
|
|
); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
#with 'Bolts::Role::Initializer'; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
has key => ( |
23
|
|
|
|
|
|
|
is => 'ro', |
24
|
|
|
|
|
|
|
isa => 'Str', |
25
|
|
|
|
|
|
|
required => 1, |
26
|
|
|
|
|
|
|
); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
has blueprint => ( |
30
|
|
|
|
|
|
|
is => 'ro', |
31
|
|
|
|
|
|
|
does => 'Bolts::Blueprint::Role::Injector', |
32
|
|
|
|
|
|
|
required => 1, |
33
|
|
|
|
|
|
|
traits => [ 'Bolts::Initializer' ], |
34
|
|
|
|
|
|
|
); |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
has does => ( |
38
|
|
|
|
|
|
|
accessor => 'does_type', |
39
|
|
|
|
|
|
|
isa => 'Moose::Meta::TypeConstraint', |
40
|
|
|
|
|
|
|
); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
has isa => ( |
44
|
|
|
|
|
|
|
accessor => 'isa_type', |
45
|
|
|
|
|
|
|
isa => 'Moose::Meta::TypeConstraint', |
46
|
|
|
|
|
|
|
); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# not actually required, we use duck-typing to determine what kind of injection |
50
|
|
|
|
|
|
|
# to perform. |
51
|
|
|
|
|
|
|
#requires 'pre_inject_value'; |
52
|
|
|
|
|
|
|
#requires 'post_inject_value'; |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub pre_inject { |
56
|
540
|
|
|
540
|
1
|
563
|
my ($self, $loc, $options, $param) = @_; |
57
|
|
|
|
|
|
|
|
58
|
540
|
100
|
|
|
|
1561
|
return unless $self->can('pre_inject_value'); |
59
|
514
|
100
|
|
|
|
822
|
return unless $self->exists($loc, $options); |
60
|
|
|
|
|
|
|
|
61
|
280
|
|
|
|
|
529
|
my $value = $self->get($loc, $options); |
62
|
279
|
|
|
|
|
706
|
$self->pre_inject_value($loc, $value, $param); |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub post_inject { |
67
|
539
|
|
|
539
|
1
|
497
|
my ($self, $loc, $options, $artifact) = @_; |
68
|
|
|
|
|
|
|
|
69
|
539
|
100
|
|
|
|
1631
|
return unless $self->can('post_inject_value'); |
70
|
26
|
50
|
|
|
|
56
|
return unless $self->exists($loc, $options); |
71
|
|
|
|
|
|
|
|
72
|
26
|
|
|
|
|
54
|
my $value = $self->get($loc, $options); |
73
|
26
|
|
|
|
|
83
|
$self->post_inject_value($loc, $value, $artifact); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub exists { |
78
|
540
|
|
|
540
|
1
|
495
|
my ($self, $loc, $options) = @_; |
79
|
|
|
|
|
|
|
|
80
|
540
|
|
|
|
|
13970
|
my $blueprint = $self->blueprint; |
81
|
540
|
|
|
|
|
12953
|
my $key = $self->key; |
82
|
|
|
|
|
|
|
|
83
|
540
|
|
|
|
|
1671
|
return $blueprint->exists($loc, $key, %$options); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
sub get { |
88
|
306
|
|
|
306
|
1
|
322
|
my ($self, $loc, $options) = @_; |
89
|
|
|
|
|
|
|
|
90
|
306
|
|
|
|
|
7570
|
my $blueprint = $self->blueprint; |
91
|
306
|
|
|
|
|
7040
|
my $key = $self->key; |
92
|
|
|
|
|
|
|
|
93
|
306
|
|
|
|
|
865
|
my $value = $blueprint->get($loc, $key, %$options); |
94
|
|
|
|
|
|
|
|
95
|
306
|
|
|
|
|
8550
|
my $isa = $self->isa_type; |
96
|
306
|
|
|
|
|
8381
|
my $does = $self->does_type; |
97
|
|
|
|
|
|
|
|
98
|
306
|
|
|
|
|
284
|
my $msg; |
99
|
306
|
100
|
|
|
|
708
|
$msg = $isa->validate($value) if defined $isa; |
100
|
306
|
50
|
0
|
|
|
26721
|
$msg //= $does->validate($value) if defined $does; |
101
|
|
|
|
|
|
|
|
102
|
306
|
100
|
|
|
|
650
|
Carp::croak(qq[Value for injection at key "$key" has the wrong type: $msg]) if $msg; |
103
|
|
|
|
|
|
|
|
104
|
305
|
|
|
|
|
490
|
return $value; |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
1; |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
__END__ |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
=pod |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
=encoding UTF-8 |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
=head1 NAME |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
Bolts::Injector - inject options and parameters into artifacts |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
=head1 VERSION |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
version 0.142930 |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 SYNOPSIS |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
package MyApp::CustomInjector; |
126
|
|
|
|
|
|
|
use Moose; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
with 'Bolts::Injector'; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub pre_inject_value { |
131
|
|
|
|
|
|
|
my ($self, $loc, $value, $param) = @_; |
132
|
|
|
|
|
|
|
$param->set($self->key, $value); |
133
|
|
|
|
|
|
|
} |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub post_inject_value { |
136
|
|
|
|
|
|
|
my ($self, $loc, $value, $artifact) = @_; |
137
|
|
|
|
|
|
|
$artifact->set($self->key, $value); |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=head1 DESCRIPTION |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Defines the interface that injectors use to inject dependencies into an artifact |
143
|
|
|
|
|
|
|
being resolved. While the locator finds the object for the caller and the |
144
|
|
|
|
|
|
|
blueprint determines how to construct the artifact, the injector helps the |
145
|
|
|
|
|
|
|
blueprint by passing through any parameters or settings needed to complete the |
146
|
|
|
|
|
|
|
construction. |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
This is done in two phases, with most injectors only implementing one of them: |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=over |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=item 1. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
B<Pre-injection.> Allows the injector to configure the parameters sent through |
155
|
|
|
|
|
|
|
to blueprint's builder method, such as might be needed when constructing a new |
156
|
|
|
|
|
|
|
object. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item 2. |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
B<Post-injection.> This phase gives the injector access to the newly constructed |
161
|
|
|
|
|
|
|
but partially incomplete object to perform additional actions on the object, |
162
|
|
|
|
|
|
|
such as calling methods to set additional attributes or activate state on the |
163
|
|
|
|
|
|
|
object. |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=back |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
This role provides the tools necessary to allow the injection implementations to |
168
|
|
|
|
|
|
|
focus only on the injection process without worrying about the value being |
169
|
|
|
|
|
|
|
injected. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=head2 init_locator |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
If provided with a reference to the meta-locator for the bag to which the injector is going to be attached, the L<blueprint> may be given as initializers. |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
=head2 key |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
This is the key used to desribe what the injector is injecting. This might be a parameter name, an array index, or method name (or any other descriptive string). |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
=head2 blueprint |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
This is the blueprint that defines how the value being injected will be constructed. So, not only is the injector part of the process of construction, but it has its own blueprint for constructing the value needed to perform the injection. |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
All the injector needs to worry about is the L</get> method, which handles the process of getting and validating the value for you. |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
Instead of passing the blueprint object in directly, you can provide an initializer in an array reference, similar to what you would pass to C<acquire> to get the blueprint from the meta-locator, e.g.: |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
blueprint => bolts_init('blueprint', 'acquire', { |
190
|
|
|
|
|
|
|
path => [ 'foo' ], |
191
|
|
|
|
|
|
|
}), |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
If so, you must provide an L</init_locator>. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=head2 does |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
This is a type constraint describing what value is expected for injection. This is checked within L</get>. |
198
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
=head2 isa |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
This is a type constraint describing what value is expected for injection. This is checked within L</get>. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=head1 OVERRIDDEN METHODS |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head2 pre_inject_value |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
$injector->pre_inject_value($loc, $value, $param); |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
This method is called first, before the artifact has been constructed by the parent blueprint. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
The C<$loc> provides the context for the injector. It is the bag that contains the artifact being constructed. The C<$value> is the value to be injected. The C<$param> is the value to inject into, which will be passed through to the blueprint for use during construction. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
If your injector does not provide any pre-injection, do not implement this method. |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
=head2 post_inject_value |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
$injector->post_inject_value($loc, $value, $artifact); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
This method is called after the blueprint has already constructed the object for additional modification. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
The C<$loc> provides the context for the injector. It is the bag that contains the artifact being constructed. The C<$value> is the value to be injected. The C<$artifact> is the constructed artifact to be injected into. |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
If your injector does not provide any post-injection, do not implement this method. |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
=head1 METHODS |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=head2 pre_inject |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
$injector->pre_inject($loc, $options, $param); |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Performs the complete process of pre-injection, calling L</pre_inject_value>, if needed. |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
=head2 post_inject |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
$injector->post_inject($loc, $options, $artifact); |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
Performs the complete process of post-injection, calling L</post_inject_value>, if needed. |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
=head2 exists |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
my $exists = $injector->exists($loc, $options); |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
Returns true if the blueprint reports the value for injection exists. Injection is skipped if it does not exists. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=head2 get |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
my $value = $injector->get($loc, $options); |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
These are used by L</pre_inject> and L</post_inject> to acquire the value to be injected. |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
=head1 AUTHOR |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Andrew Sterling Hanenkamp <hanenkamp@cpan.org> |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
This software is copyright (c) 2014 by Qubling Software LLC. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
260
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
=cut |