File Coverage

blib/lib/Rose/Object/MixIn.pm
Criterion Covered Total %
statement 60 76 78.9
branch 23 44 52.2
condition 13 29 44.8
subroutine 10 10 100.0
pod 2 5 40.0
total 108 164 65.8


line stmt bran cond sub pod time code
1             package Rose::Object::MixIn;
2              
3 1     1   7658 use strict;
  1         3  
  1         38  
4              
5 1     1   5 use Carp;
  1         2  
  1         167  
6              
7             our $Debug = 0;
8              
9             our $VERSION = '0.856';
10              
11             use Rose::Class::MakeMethods::Set
12             (
13 1         17 inheritable_set =>
14             [
15             '_export_tag' =>
16             {
17             list_method => '_export_tags',
18             clear_method => 'clear_export_tags',
19             add_method => '_add_export_tag',
20             delete_method => 'delete_export_tag',
21             deletes_method => 'delete_export_tags',
22             },
23              
24             '_pre_import_hook',
25             {
26             clear_method => 'clear_pre_import_hooks',
27             add_method => 'add_pre_import_hook',
28             adds_method => 'add_pre_import_hooks',
29             delete_method => 'delete_pre_import_hook',
30             deletes_method => 'delete_pre_import_hooks',
31             },
32             ],
33 1     1   3131 );
  1         3  
34              
35             sub import
36             {
37 3     3   904 my($class) = shift;
38              
39 3         12 my $target_class = (caller)[0];
40              
41 3         5 my($force, @methods, %import_as);
42              
43 3         14 foreach my $arg (@_)
44             {
45 7 50 66     25 if(!defined $target_class && $arg !~ /^-/)
46             {
47 1         1 $target_class = $arg;
48 1         2 next;
49             }
50              
51 6 50       41 if($arg =~ /^-?-force$/)
    100          
    100          
    100          
52             {
53 0         0 $force = 1;
54             }
55             elsif($arg =~ /^-?-target[-_]class$/)
56             {
57 1         4 $target_class = undef; # set on next iteration...lame
58 1         4 next;
59             }
60             elsif($arg =~ /^:(.+)/)
61             {
62 1 50       4 my $methods = $class->export_tag($1) or
63             croak "Unknown export tag - '$arg'";
64              
65 1         4 push(@methods, @$methods);
66             }
67             elsif(ref $arg eq 'HASH')
68             {
69 2         10 while(my($method, $name) = each(%$arg))
70             {
71 2         3 push(@methods, $method);
72 2         10 $import_as{$method} = $name;
73             }
74             }
75             else
76             {
77 2         6 push(@methods, $arg);
78             }
79             }
80              
81 3         8 foreach my $method (@methods)
82             {
83 5 50       39 my $code = $class->can($method) or
84             croak "Could not import method '$method' from $class - no such method";
85              
86 5   66     21 my $import_as = $import_as{$method} || $method;
87              
88 5 50 33     58 if($target_class->can($import_as) && !$force)
89             {
90 0         0 croak "Could not import method '$import_as' from $class into ",
91             "$target_class - a method by that name already exists. ",
92             "Pass a '-force' argument to import() to override ",
93             "existing methods."
94             }
95              
96 5 50       26 if(my $hooks = $class->pre_import_hooks($method))
97             {
98 5         14 foreach my $code (@$hooks)
99             {
100 0         0 my $error;
101              
102 0         0 TRY:
103             {
104 0         0 local $@;
105 0         0 eval { $code->($class, $method, $target_class, $import_as) };
  0         0  
106 0         0 $error = $@;
107             }
108              
109 0 0       0 if($error)
110             {
111 0         0 croak "Could not import method '$import_as' from $class into ",
112             "$target_class - $error";
113             }
114             }
115             }
116              
117 1     1   8 no strict 'refs';
  1         2  
  1         970  
118 5 50       14 $Debug && warn "${target_class}::$import_as = ${class}->$method\n";
119 5         5 *{$target_class . '::' . $import_as} = $code;
  5         33  
120             }
121             }
122              
123             sub export_tag
124             {
125 4     4 1 17 my($class, $tag) = (shift, shift);
126              
127 4 50       19 if(index($tag, ':') == 0)
128             {
129 0         0 croak 'Tag name arguments to export_tag() should not begin with ":"';
130             }
131              
132 4 100 66     36 if(@_ && !$class->_export_tag_value($tag))
133             {
134 3         30 $class->_add_export_tag($tag);
135             }
136              
137 4 50 33     40 if(@_ && (@_ > 1 || (ref $_[0] || '') ne 'ARRAY'))
      66        
138             {
139 0         0 croak 'export_tag() expects either a single tag name argument, ',
140             'or a tag name and a reference to an array of method names';
141             }
142              
143 4         15 my $ret = $class->_export_tag_value($tag, @_);
144              
145 4 50       10 croak "No such tag: $tag" unless($ret);
146              
147 4 50       21 return wantarray ? @$ret : $ret;
148             }
149              
150             sub export_tags
151             {
152 2     2 1 59 my($class) = shift;
153 2 50       7 return $class->_export_tags unless(@_);
154 2         17 $class->clear_export_tags;
155 2         726 $class->add_export_tags(@_);
156             }
157              
158             sub add_export_tags
159             {
160 2     2 0 6 my($class) = shift;
161              
162 2         7 while(@_)
163             {
164 3         6 my($tag, $arg) = (shift, shift);
165 3         18 $class->export_tag($tag, $arg);
166             }
167             }
168              
169             sub pre_import_hook
170             {
171 5     5 0 10 my($class, $method) = (shift, shift);
172              
173 5 50 33     19 if(@_ && !$class->_pre_import_hook_value($method))
174             {
175 0         0 $class->add_pre_import_hook($method);
176             }
177              
178 5 0 0     11 if(@_ && (@_ > 1 || (ref $_[0] && (ref $_[0] || '') !~ /\A(?:ARRAY|CODE)\z/)))
      33        
179             {
180 0         0 croak 'pre_import_hook() expects either a single method name argument, ',
181             'or a method name and a code reference or a reference to an array ',
182             'of code references';
183             }
184              
185 5 50       214 if(@_)
186             {
187 0 0       0 unless(ref $_[0] eq 'ARRAY')
188             {
189 0         0 $_[0] = [ $_[0] ];
190             }
191             }
192              
193 5   50     27 my $ret = $class->_pre_import_hook_value($method, @_) || [];
194              
195 5 50       24 return wantarray ? @$ret : $ret;
196             }
197              
198 5     5 0 20 sub pre_import_hooks { shift->pre_import_hook(shift) }
199              
200             1;
201              
202             __END__