File Coverage

blib/lib/Bolts/Role/RootLocator.pm
Criterion Covered Total %
statement 50 57 87.7
branch 11 20 55.0
condition 9 11 81.8
subroutine 11 11 100.0
pod 4 4 100.0
total 85 103 82.5


line stmt bran cond sub pod time code
1             package Bolts::Role::RootLocator;
2             $Bolts::Role::RootLocator::VERSION = '0.142930';
3             # ABSTRACT: Interface for locating artifacts from some root bag
4              
5 8     8   5072 use Moose::Role;
  8         7037  
  8         52  
6              
7             with 'Bolts::Role::Locator';
8              
9 8     8   32216 use Bolts::Locator;
  8         14  
  8         167  
10 8     8   30 use Bolts::Util;
  8         10  
  8         149  
11 8     8   31 use Carp ();
  8         12  
  8         107  
12 8     8   1406 use Safe::Isa;
  8         1019  
  8         1027  
13 8     8   40 use Scalar::Util ();
  8         12  
  8         3667  
14              
15              
16             # TODO Rename root to something better.
17             requires 'root';
18              
19              
20             sub acquire {
21 363     363 1 24157 my ($self, @path) = @_;
22             # use Data::Dumper;
23             # Carp::cluck(Dumper(\@path));
24              
25 363         490 my $options = {};
26 363 100 100     1567 if (@path > 1 and ref $path[-1]) {
27 227         280 $options = pop @path;
28             }
29            
30 363         508 my $current_path = '';
31              
32 363         956 my $item = $self->root;
33 363         667 while (@path) {
34 661         754 my $component = shift @path;
35              
36 661         655 my $bag = $item;
37 661         1204 $item = $self->_get_from($bag, $component, $current_path);
38 661         1517 $item = $self->resolve($bag, $item, $options);
39              
40 659 100       1294 $current_path .= ' ' if $current_path;
41 659         2068 $current_path .= qq["$component"];
42             }
43              
44 361         1536 return $item;
45             }
46              
47              
48             sub acquire_all {
49 31     31 1 59 my ($self, @path) = @_;
50              
51 31         44 my $options = {};
52 31 50 33     102 if (@path > 1 and ref $path[-1]) {
53 0         0 $options = pop @path;
54             }
55            
56 31         80 my $bag = $self->acquire(@path);
57 31 50       112 if (ref $bag eq 'ARRAY') {
58             return [
59 31         66 map { $self->resolve($bag, $_, $options) } @$bag
  31         55  
60             ];
61             }
62              
63             else {
64 0         0 return [];
65             }
66             }
67              
68              
69             sub resolve {
70 692     692 1 736 my ($self, $bag, $item, $options) = @_;
71              
72 692 100 100     1353 return $item->get($bag, %$options)
73             if $item->$_can('does')
74             and $item->$_does('Bolts::Role::Artifact');
75              
76 317         31660 return $item;
77             }
78              
79              
80             sub get {
81 1     1 1 3 my ($self, $component) = @_;
82 1         5 return $self->_get_from($self->root, $component);
83             }
84              
85             sub _get_from {
86 662     662   858 my ($self, $bag, $component, $current_path) = @_;
87 662   100     1091 $current_path //= '';
88              
89 662 50       1030 Carp::croak("unable to acquire artifact for [$current_path]")
90             unless defined $bag;
91              
92             # A bag can be any blessed object...
93 662 50       1712 if (Scalar::Util::blessed($bag)) {
    0          
    0          
94              
95             # So long as it has that method
96 662 50       1831 if ($bag->can($component)) {
97 662         8928 return $bag->$component;
98             }
99            
100             else {
101 0           Carp::croak(qq{no artifact named "$component" at [$current_path]});
102             }
103             }
104              
105             # Or any unblessed hash
106             elsif (ref $bag eq 'HASH') {
107 0           return $bag->{ $component };
108             }
109              
110             # Or any unblessed array
111             elsif (ref $bag eq 'ARRAY') {
112 0           return $bag->[ $component ];
113             }
114              
115             # But nothing else...
116             else {
117 0           my $path = join ' ', grep defined, $current_path, $component;
118 0           Carp::croak(qq{not able to acquire artifact for [$path]});
119             }
120             }
121              
122             1;
123              
124             __END__
125              
126             =pod
127              
128             =encoding UTF-8
129              
130             =head1 NAME
131              
132             Bolts::Role::RootLocator - Interface for locating artifacts from some root bag
133              
134             =head1 VERSION
135              
136             version 0.142930
137              
138             =head1 DESCRIPTION
139              
140             This is the interface that any locator must implement. A locator's primary job is to provide a way to find artifacts within a bag or selection of bags. This performs the acquisition and resolution process. This actually also implements everything needed for the process except for the L</root>.
141              
142             =head1 ROLES
143              
144             =over
145              
146             =item *
147              
148             L<Bolts::Role::Locator>
149              
150             =back
151              
152             =head1 REQUIRED METHODS
153              
154             =head2 root
155              
156             This is the object to use as the bag to start searching. It may be an object, a reference to an array, or a reference to a hash.
157              
158             B<Caution:> This will be renamed in the future.
159              
160             =head1 METHODS
161              
162             =head2 acquire
163              
164             my $artifact = $loc->acquire(@path, \%options);
165              
166             Given a C<@path> of symbol names to traverse, this goes through each artifact in turn, resolves it, if necessary, and then continues to the next path component.
167              
168             After it finds the artifact, it will resolve the artifact using the L</resolve> method, which is passed the (optional) B<%options>.
169              
170             When complete, the complete, resolved artifact found is returned.
171              
172             =head2 acquire_all
173              
174             my @artifacts = @{ $loc->acquire_all(\@path) };
175              
176             This is similar to L<acquire>, but if the last bag is a reference to an array, then all the artifacts within that bag are acquired, resolved, and returned as a reference to an array.
177              
178             If the last item found at the path is not an array, it returns an empty list.
179              
180             =head2 resolve
181              
182             my $resolved_artifact = $loc->resolve($bag, $artifact, \%options);
183              
184             After the artifact has been found, this method resolves the a partial artifact implementing the L<Bolts::Role::Artifact> and turns it into the complete artifact.
185              
186             =head2 get
187              
188             my $artifact = $log->get($component);
189              
190             Given a single symbol name as the path component to find during acquisition it returns the partial artifact for it. This artifact is incomplete and still needs to be resolved.
191              
192             =head1 AUTHOR
193              
194             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
195              
196             =head1 COPYRIGHT AND LICENSE
197              
198             This software is copyright (c) 2014 by Qubling Software LLC.
199              
200             This is free software; you can redistribute it and/or modify it under
201             the same terms as the Perl 5 programming language system itself.
202              
203             =cut