File Coverage

blib/lib/Object/Container/Exporter.pm
Criterion Covered Total %
statement 99 104 95.1
branch 24 36 66.6
condition 18 22 81.8
subroutine 23 24 95.8
pod 6 7 85.7
total 170 193 88.0


line stmt bran cond sub pod time code
1             package Object::Container::Exporter;
2 6     6   206444 use strict;
  6         89  
  6         250  
3 6     6   32 use warnings;
  6         11  
  6         162  
4 6     6   5950 use parent 'Class::Singleton';
  6         2095  
  6         33  
5 6     6   15251 use Class::Load ();
  6         326406  
  6         755  
6              
7             our $VERSION = '0.03';
8              
9             sub import {
10 11     11   188 my ($class, @opts) = @_;
11              
12 11         80 my $caller = caller;
13              
14 11 100 50     225 if (scalar(@opts) == 1 and ($opts[0]||'') =~ /^-base$/i) {
    100 100        
      50        
      100        
15              
16             {
17 6     6   55 no strict 'refs';
  6         12  
  6         529  
  5         10  
18 5         8 push @{"${caller}::ISA"}, $class;
  5         89  
19             }
20              
21 5         16 for my $func (qw/register register_namespace register_default_container_name/) {
22 15         107 my $code = $class->can($func);
23 6     6   34 no strict 'refs'; ## no critic.
  6         12  
  6         3147  
24 15     10   55 *{"$caller\::$func"} = sub { $code->($caller, @_) };
  15         88  
  10         61  
25             }
26              
27 5         440 return;
28             }
29             elsif(scalar(@opts) >= 1 and ($opts[0]||'') !~ /^-no_export/i) {
30 1         7 $class->_export_functions($caller => @opts);
31             }
32              
33 6 100 100     154 unless (($opts[0]||'') =~ /^-no_export$/i) {
34 5         31 $class->_export_container($caller);
35             }
36             }
37              
38             sub base_name {
39 4     4 0 4 my $class = shift;
40 4 50       18 $class = ref $class unless $class;
41 4         52 (my $base_name = $class) =~ s/(::.+)?$//g;
42 4         13 $base_name;
43             }
44              
45             sub load_class {
46 5     5 1 51 my ($class, $pkg) = @_;
47 5         39 Class::Load::load_class($pkg);
48             }
49              
50             sub _camelize {
51 18     18   27 my $s = shift;
52 18         123 join('', map{ ucfirst $_ } split(/(?<=[A-Za-z])_(?=[A-Za-z])|\b/, $s));
  34         111  
53             }
54              
55             sub _export_functions {
56 1     1   3 my ($self, $caller, @export_names) = @_;
57              
58 1 50       8 $self = $self->instance unless ref $self;
59              
60 1         10 for my $name (@export_names) {
61              
62 2 50       18 if ($caller->can($name)) { die qq{can't export $name for $caller. $name already defined in $caller.} }
  0         0  
63              
64             my $code = $self->{_register_namespace}->{$name} || sub {
65 4     4   1421 my $target = shift;
66 4         23 my $container_name = join '::', $self->base_name, _camelize($name), _camelize($target);
67 4 50       27 return $target ? $self->get($container_name) : $self;
68 2   100     11 };
69              
70             {
71 6     6   36 no strict 'refs';
  6         20  
  6         1150  
  2         3  
72 2         3 *{"${caller}::${name}"} = $code;
  2         6  
73             }
74             }
75             }
76              
77             sub _export_container {
78 5     5   22 my ($class, $caller) = @_;
79              
80 5   100     26 my $container_name = $class->instance->{_default_container_name} || 'container';
81              
82 5 50       150 if ($caller->can($container_name)) { die qq{can't export '$container_name' for $caller. '$container_name' already defined in $caller.} }
  0         0  
83             my $code = sub {
84 10     10   4507 my $target = shift;
85 10 50       95 return $target ? $class->get($target) : $class;
86 5         22 };
87             {
88 6     6   41 no strict 'refs';
  6         16  
  6         3389  
  5         11  
89 5         7 *{"${caller}::${container_name}"} = $code;
  5         9424  
90             }
91             }
92              
93             sub register {
94 5     5 1 15 my ($self, $class, @init_opt) = @_;
95 5 50       30 $self = $self->instance unless ref $self;
96              
97 5         43 my $initializer;
98 5 50 33     42 if (@init_opt == 1 and ref($init_opt[0]) eq 'CODE') {
99 5         10 $initializer = $init_opt[0];
100             }
101             else {
102             $initializer = sub {
103 0     0   0 Class::Load::load_class($class);
104 0         0 $class->new(@init_opt);
105 0         0 };
106             }
107              
108 5         25 $self->{_registered_classes}->{$class} = $initializer;
109             }
110              
111             sub register_namespace {
112 4     4 1 9 my ($self, $method, $pkg) = @_;
113 4 50       81 $self = $self->instance unless ref $self;
114 4         121 my $class = ref $self;
115              
116 4         13 $pkg = _camelize($pkg);
117             my $code = sub {
118 6     6   6159 my $target = shift;
119 6         16 my $container_name = join '::', $pkg, _camelize($target);
120 6         23 Class::Load::load_class($container_name);
121 4 50       972 return $target ? $class->get($container_name) : $class;
122 4         22 };
123              
124 4         44 $self->{_register_namespace}->{$method} = $code;
125             }
126              
127             sub register_default_container_name {
128 1     1 1 2 my ($self, $name) = @_;
129 1 50       14 $self = $self->instance unless ref $self;
130 1         36 $self->{_default_container_name} = $name;
131             }
132              
133             sub get {
134 19     19 1 3672 my ($self, $class) = @_;
135 19 100       121 $self = $self->instance unless ref $self;
136              
137 19   100     325 my $obj = $self->{_inflated_classes}->{$class} ||= do {
138 10         29 my $initializer = $self->{_registered_classes}->{$class};
139 10 100       79 $initializer ? $initializer->($self) : ();
140             };
141              
142              
143 19 100       3781 return $obj if $obj;
144              
145 5         21 Class::Load::load_class($class);
146 2         798 $obj = $self->{_inflated_classes}->{$class} = $class->new;
147 2         20 $obj;
148             }
149              
150             sub remove {
151 1     1 1 14 my ($self, $class) = @_;
152 1 50       8 $self = $self->instance unless ref $self;
153 1         13 delete $self->{_inflated_classes}->{$class};
154             }
155              
156             1;
157             __END__