File Coverage

blib/lib/Bread/Board/Container/Parameterized.pm
Criterion Covered Total %
statement 39 39 100.0
branch 5 8 62.5
condition n/a
subroutine 10 10 100.0
pod 3 3 100.0
total 57 60 95.0


line stmt bran cond sub pod time code
1             package Bread::Board::Container::Parameterized;
2             our $AUTHORITY = 'cpan:STEVAN';
3             $Bread::Board::Container::Parameterized::VERSION = '0.35';
4 53     53   393 use Moose;
  53         121  
  53         403  
5 53     53   262324 use Moose::Util 'find_meta';
  53         150  
  53         405  
6 53     53   31721 use Bread::Board::Container::FromParameterized;
  53         205  
  53         2278  
7             # ABSTRACT: A parameterized container
8              
9 53     53   488 use Bread::Board::Container;
  53         133  
  53         19722  
10              
11             with 'Bread::Board::Traversable';
12              
13             has 'name' => (
14             is => 'rw',
15             isa => 'Str',
16             required => 1
17             );
18              
19             has 'allowed_parameter_names' => (
20             is => 'ro',
21             isa => 'ArrayRef',
22             required => 1,
23             );
24              
25             has 'container' => (
26             is => 'ro',
27             isa => 'Bread::Board::Container',
28             lazy => 1,
29             builder => '_build_container',
30             handles => [qw[
31             add_service
32             get_service
33             has_service
34             get_service_list
35             has_services
36             services
37              
38             add_sub_container
39             get_sub_container
40             has_sub_container
41             get_sub_container_list
42             has_sub_containers
43             sub_containers
44             ]]
45             );
46              
47             sub _build_container {
48 10     10   22 my $self = shift;
49 10         329 Bread::Board::Container->new( name => $self->name )
50             }
51              
52 3     3 1 1698 sub fetch { die "Cannot fetch from a parameterized container"; }
53 1     1 1 884 sub resolve { die "Cannot resolve from a parameterized container"; }
54              
55             sub create {
56 13     13 1 3220 my ($self, %params) = @_;
57              
58 13         37 my @allowed_names = sort @{ $self->allowed_parameter_names };
  13         520  
59 13         62 my @given_names = sort keys %params;
60              
61 13 50       54 (scalar @allowed_names == scalar @given_names)
62             || confess "You did not pass the correct number of parameters";
63              
64 13 50       95 ((join "" => @allowed_names) eq (join "" => @given_names))
65             || confess "Incorrect parameter list, got: ("
66             . (join "" => @given_names)
67             . ") expected: ("
68             . (join "" => @allowed_names)
69             . ")";
70              
71              
72 13 50       485 my $clone = $self->container->clone(
73             name => ($self->container->name eq $self->name
74             ? join "|" => $self->name, @given_names
75             : $self->container->name)
76             );
77              
78 13         653 my $from_parameterized_meta = find_meta('Bread::Board::Container::FromParameterized');
79 13         249 $clone = $from_parameterized_meta->rebless_instance($clone);
80              
81 13 100       38056 if ($self->has_parent) {
82 6         204 my $cloned_parent = $self->parent->clone;
83              
84             $cloned_parent->sub_containers({
85 6         232 %{ $cloned_parent->sub_containers },
  6         207  
86             $self->name => $clone,
87             });
88              
89 6         222 $clone->parent($cloned_parent);
90             }
91              
92 13         55 foreach my $key ( @given_names ) {
93             $clone->add_sub_container(
94 13         81 $params{ $key }->clone( name => $key )
95             );
96             }
97              
98 13         120 $clone;
99             }
100              
101             __PACKAGE__->meta->make_immutable;
102              
103 53     53   420 no Moose; no Moose::Util; 1;
  53     53   212  
  53         372  
  53         14188  
  53         128  
  53         2253  
104              
105             __END__
106              
107             =pod
108              
109             =encoding UTF-8
110              
111             =head1 NAME
112              
113             Bread::Board::Container::Parameterized - A parameterized container
114              
115             =head1 VERSION
116              
117             version 0.35
118              
119             =head1 DESCRIPTION
120              
121             This class implements a sort of container factory for L<Bread::Board>:
122             a parameterized container is a, in practice, a function from a set of
123             parameters (which must be containers) to an actual container. See
124             L<Bread::Board::Manual::Example::FormSensible> for an example.
125              
126             =head1 ATTRIBUTES
127              
128             =head2 C<name>
129              
130             Read/write string, required. Every container needs a name, by which it
131             can be referenced when L<fetching it|Bread::Board::Traversable/fetch>.
132              
133             =head2 C<allowed_parameter_names>
134              
135             Read-only arrayref of strings, required. These are the names of the
136             containers that must be passed to L<< C<create>|create ( %params ) >>
137             to get an actual container out of this parameterized object.
138              
139             =head2 C<container>
140              
141             This attribute holds the "prototype" container. Services inside it can
142             depend on service paths that include the container names given in
143             L</allowed_parameter_names>.
144              
145             =head1 METHODS
146              
147             =head2 C<add_service>
148              
149             =head2 C<get_service>
150              
151             =head2 C<has_service>
152              
153             =head2 C<get_service_list>
154              
155             =head2 C<has_services>
156              
157             =head2 C<add_sub_container>
158              
159             =head2 C<get_sub_container>
160              
161             =head2 C<has_sub_container>
162              
163             =head2 C<get_sub_container_list>
164              
165             =head2 C<has_sub_containers>
166              
167             All these methods are delegated to the "prototype" L</container>, so
168             that this object can be defined as if it were a normal container.
169              
170             =head2 C<create>
171              
172             my $container = $parameterized_container->create(%params);
173              
174             After checking that the keys of C<%params> are exactly the same
175             strings that are present in L</allowed_parameter_names>, this method
176             clones the prototype L</container>, adds the C<%params> to the clone
177             as sub-containers, and returns the clone.
178              
179             If this was not a top-level container, the parent is also cloned, and
180             the container clone is added to the parent clone.
181              
182             Please note that the container returned by this method does I<not>
183             have the same name as the parameterized container, and that calling
184             this method with different parameter values will return different
185             containers, but all with the same name. It's probably a bad idea to
186             instantiate a non-top-level parameterized container more than once.
187              
188             =head2 C<fetch>
189              
190             =head2 C<resolve>
191              
192             These two methods die, since services in a parameterized container
193             won't usually resolve, and attempting to do so is almost always a
194             mistake.
195              
196             =head1 AUTHOR
197              
198             Stevan Little <stevan@iinteractive.com>
199              
200             =head1 BUGS
201              
202             Please report any bugs or feature requests on the bugtracker website
203             https://github.com/stevan/BreadBoard/issues
204              
205             When submitting a bug or request, please include a test-file or a
206             patch to an existing test-file that illustrates the bug or desired
207             feature.
208              
209             =head1 COPYRIGHT AND LICENSE
210              
211             This software is copyright (c) 2017, 2016, 2015, 2014, 2013, 2011, 2009 by Infinity Interactive.
212              
213             This is free software; you can redistribute it and/or modify it under
214             the same terms as the Perl 5 programming language system itself.
215              
216             =cut