File Coverage

lib/Peco/Container.pm
Criterion Covered Total %
statement 45 81 55.5
branch 11 30 36.6
condition 8 11 72.7
subroutine 14 18 77.7
pod 7 13 53.8
total 85 153 55.5


line stmt bran cond sub pod time code
1             package Peco::Container;
2              
3 7     7   144230 use strict;
  7         16  
  7         251  
4              
5 7     7   40 use Carp ();
  7         17  
  7         128  
6 7     7   2187 use Peco::Spec;
  7         16  
  7         8130  
7              
8             our $VERSION = '1.2';
9              
10             sub new {
11 7     7 0 71 my ( $class ) = @_;
12 7         33 my $self = bless {
13             specs => { },
14             }, $class;
15 7         48 $self;
16             }
17              
18             sub register {
19 13     13 1 9162 my ( $self, $key, $class, $deps, $ctor, $attrs ) = @_;
20 13   33     42 $class ||= $key;
21 13   100     63 $deps ||= [ ];
22 13   100     64 $ctor ||= 'new';
23 13   100     109 $attrs ||= { };
24              
25 13         45 $self->_assert_not_exists( $key );
26              
27 13         17 my $spec;
28 13         30 my @spec = ( $class, $deps, $ctor, $attrs );
29              
30 13 100       534 if ( ref $class ) {
31 2 50       4 if ( ref $class eq 'CODE' ) {
32 2         13 $spec = Peco::Spec::Code->new( @spec );
33             }
34             else {
35 0         0 $spec = Peco::Spec::Const->new( @spec );
36             }
37             } else {
38 11 100       106 if ( UNIVERSAL::isa( $class, 'Peco::Spec' ) ) {
    100          
    50          
39 1         6 $spec = $class->new( @spec );
40             }
41             elsif ( UNIVERSAL::isa( $class, 'UNIVERSAL' ) ) {
42 7         46 $spec = Peco::Spec::Class->new( @spec );
43             }
44             elsif ( index( $class, '::' ) != -1 ) {
45             # we get here if the class looks like a class but hasn't
46             # been `require'd or `use'd... it's a bit of a nasty
47             # heuristic, but a dumb machine can be only so smart
48 0         0 eval "require $class; $class->import();";
49 0 0       0 if ( $@ ) {
50 0         0 my $file = join( '/', split /::/, $class ).'.pm';
51 0 0       0 if ( exists $INC{ $file } ) {
52 0         0 Carp::croak $@;
53             } else {
54 0         0 $spec = Peco::Spec::Const->new( @spec );
55             }
56             } else {
57 0 0       0 if ( UNIVERSAL::isa( $class, 'Peco::Spec' ) ) {
58 0         0 $spec = $class->new( @spec );
59             } else {
60 0         0 $spec = Peco::Spec::Class->new( @spec );
61             }
62             }
63             }
64             else {
65 3         25 $spec = Peco::Spec::Const->new( @spec );
66             }
67             }
68              
69 13         35 $self->specs->{$key} = $spec;
70             }
71              
72             sub unregister {
73 0     0 0 0 my ( $self, $key ) = @_;
74 0         0 $self->_assert_exists( $key );
75 0         0 return delete $self->specs->{$key};
76             }
77              
78             sub service {
79 17     17 1 1967 my ( $self, $key, %seen ) = @_;
80 17 50       34 if ( $self->contains( $key ) ) {
    0          
81 17         43 return $self->spec( $key )->instance( $self, $key, %seen );
82             }
83             elsif ( UNIVERSAL::isa( $key, 'UNIVERSAL' ) ) {
84 0         0 my $type = $key;
85 0         0 foreach my $key ( $self->keys ) {
86 0 0       0 if ( UNIVERSAL::isa( $self->specs->{$key}->class, $type ) ) {
87 0         0 return $self->specs->{$key}->instance( $self, $type, %seen );
88             }
89             }
90             }
91 0         0 $self->_assert_exists( $key );
92 0         0 return ();
93             }
94              
95             sub contains {
96 49     49 1 61 my ( $self, $key ) = @_;
97 49         102 exists $self->specs->{ $key };
98             }
99              
100             sub services {
101 0     0 1 0 my ( $self ) = @_;
102 0         0 map { $self->service( $_ ) } $self->keys();
  0         0  
103             }
104              
105 8     8 0 10 sub keys { CORE::keys %{ $_[0]->specs } }
  8         21  
106              
107             sub spec {
108 18     18 0 25 my ( $self, $key ) = @_;
109 18         41 $self->_assert_exists( $key );
110 18         38 $self->specs->{ $key };
111             }
112              
113 88   50 88 0 518 sub specs { $_[0]{specs} ||= { } }
114 8     8 1 29 sub count { scalar( $_[0]->keys() ) }
115              
116             sub clone {
117 0     0 0 0 my ( $self, $deep ) = @_;
118 0         0 my $copy = ref( $self )->new;
119 0         0 my %specs;
120 0         0 foreach my $key ( CORE::keys %{ $self->specs } ) {
  0         0  
121 0 0       0 if ( $self->specs->{ $key }->can( 'clone' ) ) {
122 0         0 $specs{ $key } = $self->specs->{ $key }->clone( $deep );
123             } else {
124 0         0 $specs{ $key } = $self->specs->{ $key };
125             }
126             }
127 0         0 $copy->{specs} = \%specs;
128 0         0 return $copy;
129             }
130              
131 4     4 1 1754 sub is_empty { $_[0]->count == 0 }
132              
133             sub multicast {
134 0     0 1 0 my ( $self, $method, @args ) = @_;
135 0         0 my @keys = $self->keys;
136 0         0 foreach ( $self->services ) {
137 0 0       0 $_->$method( @args ) if UNIVERSAL::can( $_, $method );
138             }
139             }
140              
141             sub _assert_exists {
142 18     18   19 my ( $self, $key ) = @_;
143 18 50       33 Carp::confess("no such spec: `$key'") unless $self->contains( $key );
144             }
145              
146             sub _assert_not_exists {
147 13     13   24 my ( $self, $key ) = @_;
148 13 50       37 Carp::confess( "spec already exists: `$key'" ) if $self->contains( $key );
149             }
150              
151             1;
152              
153             __END__