line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Fukurama::Class::AttributesHandler;
|
2
|
5
|
|
|
5
|
|
34922
|
use Fukurama::Class::Version(0.01);
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
33
|
|
3
|
5
|
|
|
5
|
|
38
|
use Fukurama::Class::Rigid;
|
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
30
|
|
4
|
5
|
|
|
5
|
|
30
|
use Fukurama::Class::Carp;
|
|
5
|
|
|
|
|
17
|
|
|
5
|
|
|
|
|
40
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
my $ATT_METHODS;
|
7
|
|
|
|
|
|
|
my $EXPORTED;
|
8
|
|
|
|
|
|
|
my $LAST_ATTRIBUTE_METHOD;
|
9
|
|
|
|
|
|
|
my $SUBS;
|
10
|
|
|
|
|
|
|
my $HELPER_METHODS;
|
11
|
|
|
|
|
|
|
BEGIN {
|
12
|
5
|
|
|
5
|
|
15
|
$ATT_METHODS = {};
|
13
|
5
|
|
|
|
|
27
|
$EXPORTED = {};
|
14
|
5
|
|
|
|
|
11
|
$SUBS = {};
|
15
|
5
|
|
|
|
|
9
|
$LAST_ATTRIBUTE_METHOD = undef;
|
16
|
5
|
|
|
|
|
443
|
$HELPER_METHODS = {};
|
17
|
|
|
|
|
|
|
}
|
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 NAME
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
Fukurama::Class::AttributesHandler - Helper class to provide corrrect handling of attributes
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
=head1 VERSION
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
Version 0.01 (beta)
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
{
|
30
|
|
|
|
|
|
|
package MyAttributeHandler;
|
31
|
|
|
|
|
|
|
sub MyAttribute {
|
32
|
|
|
|
|
|
|
my $class = $_[0];
|
33
|
|
|
|
|
|
|
my $method_data = $_[1];
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
warn("Method '$method_data->{'sub_name'}' was resolved at compiletime with data: '$method_data->{'data'}'");
|
36
|
|
|
|
|
|
|
# says: Method 'my_own_method' was resolved at compiletime with data: 'foo, bar'
|
37
|
|
|
|
|
|
|
}
|
38
|
|
|
|
|
|
|
}
|
39
|
|
|
|
|
|
|
{
|
40
|
|
|
|
|
|
|
package MyClass;
|
41
|
|
|
|
|
|
|
use Fukurama::Class::AttributesHandler();
|
42
|
|
|
|
|
|
|
Fukurama::Class::AttributesHandler->register_attributes('MyAttributeHandler');
|
43
|
|
|
|
|
|
|
Fukurama::Class::AttributesHandler->export('MyClass');
|
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
sub my_own_method : MyAttribute(foo, bar) {}
|
46
|
|
|
|
|
|
|
}
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
This module enables the possibility to define your own subroutine-attributes. This is also done with the CPAN L module
|
51
|
|
|
|
|
|
|
but here you get extra information for the subroutine, which use the attribute. E.g. the resolved methodname.
|
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
This helper class is used from Fukurama::Class::Attribute::OOStandard to enable the OO-method-signatures.
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head1 EXPORT
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
=over 4
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=item MODIFY_CODE_ATTRIBUTES
|
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
would be decorated if it exist or created if it isn't in the current class.
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
=back
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=head1 METHODS
|
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
=over 4
|
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item register_attributes( attribute_handler_class:STRING ) return:BOOLEAN
|
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Register a handler class which defines attributes. See L below
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=item export( export_to_class:STRING ) return:BOOLEAN
|
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
This will export or decorate the MODIFY_CODE_ATTRIBUTES to the export_to_class class. Be sure that you call this method
|
76
|
|
|
|
|
|
|
in a BEGIN block. Perl check them all at compiletime and croak, if some is not defined.
|
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
=item get_registered_subs( ) return:HASHREF
|
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
Get the method-definitions from all methods in your code, which use attributes over this attribute handler.
|
81
|
|
|
|
|
|
|
This is to check th code structure (or to create some documentation...)
|
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item register_helper_method( methodname:STRING ) return:VOID
|
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
All registered methodnames would be omitted as attributes, when a attribute-handler-class is parsed. But
|
86
|
|
|
|
|
|
|
if they are missed in a attribute-handler-class, the registration would fail.
|
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
=item run_check( ) return:VOID
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
Resolve all method names, which are unresolved at compiletime, and calls the atribute-definition-methods
|
91
|
|
|
|
|
|
|
in the handler-class. This is a helper method for static perl (see Fukurama::Class > BUGS)
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=back
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head1 How to define an attribute-handler-class
|
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
All methods of an attribute-handler-class have to be attribute-definitions, except these, which are registered via register helper methods.
|
98
|
|
|
|
|
|
|
This methods have to start with an uppercase letter (it is a perl specification). They will get a hash reference as single parameter.
|
99
|
|
|
|
|
|
|
In this hash you will find information of the method which use your attribute. They are:
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
=over 4
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=item class:STRING
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
The name of the class, which contain the subroutine which use the attribute (*puh*). Can be empty in some cases. Look at L.
|
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
=item sub_name:STRING
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
The resolved name of the subroutine, which use the attribute. Perls attributes doesn't resolve the name by itself,
|
110
|
|
|
|
|
|
|
so you will normally only get the sub-reference and not the name. It can be empty in some cases. Look at L.
|
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
=item data:STRING
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
The defined attribute-data. if you say 'sub new : MyAtt(this is a $test)' you will get the string 'this is a $test'.
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
=item sub:CODEREF
|
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
The code-refrence of the subroutine, which use the attribute.
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item resolved:BOOLEAN
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
A flag for the status of method name resolving for this method. In some cases, if you force a call, this flag will
|
123
|
|
|
|
|
|
|
be FALSE and the B will be empty.
|
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
=item attribute:STRING
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
The name of the attribute. This is the same like the name of your attribute-method.
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=item handler:HASHREF
|
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
A reference to your attribute class and to the actual attribute method.
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=item executed: BOOLEAN
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
An internal flag to avoid double callings of your attribute-methods.
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=back
|
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
=head1 AUTHOR, BUGS, SUPPORT, ACKNOWLEDGEMENTS, COPYRIGHT & LICENSE
|
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
see perldoc of L
|
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
=cut
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
# STATIC boolean
|
146
|
|
|
|
|
|
|
sub register_attributes {
|
147
|
7
|
|
|
7
|
1
|
7491
|
my $class = $_[0];
|
148
|
7
|
|
|
|
|
12
|
my $attribute_class = $_[1];
|
149
|
|
|
|
|
|
|
|
150
|
7
|
|
|
|
|
16
|
my @subs = ();
|
151
|
7
|
|
|
|
|
27
|
my $check_methods_exist = {};
|
152
|
|
|
|
|
|
|
{
|
153
|
|
|
|
|
|
|
|
154
|
5
|
|
|
5
|
|
27
|
no strict 'refs';
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
2835
|
|
|
7
|
|
|
|
|
11
|
|
155
|
|
|
|
|
|
|
|
156
|
7
|
|
|
|
|
103
|
my %symbols = %{$attribute_class . '::'};
|
|
7
|
|
|
|
|
107
|
|
157
|
7
|
50
|
66
|
1
|
|
124
|
if(!scalar(%symbols) && !eval("use $attribute_class;return 1;")) {
|
|
1
|
|
|
|
|
492
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
158
|
1
|
|
|
|
|
7
|
_croak("Failed to load attribute-class '$attribute_class' (maybe this class is empty?): $@\n");
|
159
|
0
|
|
|
|
|
0
|
return 0;
|
160
|
|
|
|
|
|
|
}
|
161
|
6
|
|
|
|
|
35
|
foreach my $name (keys(%symbols)) {
|
162
|
55
|
100
|
|
|
|
53
|
next if(!*{$attribute_class . '::' . $name}{'CODE'});
|
|
55
|
|
|
|
|
238
|
|
163
|
14
|
100
|
|
|
|
40
|
if($HELPER_METHODS->{$name}) {
|
164
|
5
|
|
|
|
|
11
|
$check_methods_exist->{$name} = 1;
|
165
|
5
|
|
|
|
|
13
|
next;
|
166
|
|
|
|
|
|
|
}
|
167
|
9
|
|
|
|
|
30
|
push(@subs, $name);
|
168
|
|
|
|
|
|
|
}
|
169
|
|
|
|
|
|
|
}
|
170
|
|
|
|
|
|
|
|
171
|
6
|
|
|
|
|
16
|
my @missed_helper_methods = ();
|
172
|
6
|
|
|
|
|
19
|
foreach my $name (keys(%$HELPER_METHODS)) {
|
173
|
6
|
100
|
|
|
|
31
|
next if($check_methods_exist->{$name});
|
174
|
1
|
|
|
|
|
3
|
push(@missed_helper_methods, $name);
|
175
|
|
|
|
|
|
|
}
|
176
|
6
|
100
|
|
|
|
20
|
if(scalar(@missed_helper_methods)) {
|
177
|
1
|
|
|
|
|
3
|
my $msg = join("', '", @missed_helper_methods);
|
178
|
1
|
|
|
|
|
6
|
_croak("Needed helper method(s) '$msg' is/are not defined in attribute-class '$attribute_class'. (Maybe class is not compiled yet?)");
|
179
|
|
|
|
|
|
|
}
|
180
|
|
|
|
|
|
|
|
181
|
5
|
|
|
|
|
12
|
foreach my $name (@subs) {
|
182
|
8
|
|
|
|
|
71
|
$class->_register_attribute($attribute_class, $name, 0);
|
183
|
|
|
|
|
|
|
}
|
184
|
4
|
|
|
|
|
10
|
foreach my $name (@subs) {
|
185
|
7
|
|
|
|
|
22
|
$class->_register_attribute($attribute_class, $name, 1);
|
186
|
|
|
|
|
|
|
}
|
187
|
4
|
|
|
|
|
31
|
return 1;
|
188
|
|
|
|
|
|
|
}
|
189
|
|
|
|
|
|
|
# STATIC hashref
|
190
|
|
|
|
|
|
|
sub get_registered_subs {
|
191
|
0
|
|
|
0
|
1
|
0
|
my $class = $_[0];
|
192
|
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
0
|
return $SUBS;
|
194
|
|
|
|
|
|
|
}
|
195
|
|
|
|
|
|
|
# STATIC void
|
196
|
|
|
|
|
|
|
sub _register_attribute {
|
197
|
15
|
|
|
15
|
|
24
|
my $class = $_[0];
|
198
|
15
|
|
|
|
|
17
|
my $attribute_class = $_[1];
|
199
|
15
|
|
|
|
|
61
|
my $name = $_[2];
|
200
|
15
|
|
|
|
|
18
|
my $execute_register = $_[3];
|
201
|
|
|
|
|
|
|
|
202
|
15
|
50
|
|
|
|
38
|
if($ATT_METHODS->{$name}) {
|
203
|
0
|
|
|
|
|
0
|
_croak("Attribute '$name' from attribute-class '$attribute_class' always registered for '$ATT_METHODS->{$name}->{'class'}'", 1);
|
204
|
0
|
|
|
|
|
0
|
return;
|
205
|
|
|
|
|
|
|
}
|
206
|
15
|
100
|
|
|
|
59
|
if($name !~ m/^[A-Z]/) {
|
207
|
1
|
|
|
|
|
4
|
my $helper_msg = "'" . join("', '", keys(%$HELPER_METHODS)) . "'";
|
208
|
1
|
|
|
|
|
8
|
_croak("Every attribute must start with an uppercase letter (except the helper-method(s) $helper_msg " .
|
209
|
|
|
|
|
|
|
"which is/are not an attribute).\n" .
|
210
|
|
|
|
|
|
|
"Attribute '$name' from attribute-class '$attribute_class' is not allowed.", 1);
|
211
|
0
|
|
|
|
|
0
|
return;
|
212
|
|
|
|
|
|
|
}
|
213
|
|
|
|
|
|
|
|
214
|
14
|
100
|
|
|
|
51
|
return if(!$execute_register);
|
215
|
|
|
|
|
|
|
{
|
216
|
|
|
|
|
|
|
|
217
|
5
|
|
|
5
|
|
30
|
no strict 'refs';
|
|
5
|
|
|
|
|
10
|
|
|
5
|
|
|
|
|
1134
|
|
|
7
|
|
|
|
|
12
|
|
218
|
|
|
|
|
|
|
|
219
|
7
|
|
|
|
|
51
|
$ATT_METHODS->{$name} = {
|
220
|
|
|
|
|
|
|
class => $attribute_class,
|
221
|
7
|
|
|
|
|
11
|
coderef => *{$attribute_class . '::' . $name}{'CODE'},
|
222
|
|
|
|
|
|
|
};
|
223
|
|
|
|
|
|
|
}
|
224
|
7
|
|
|
|
|
24
|
return;
|
225
|
|
|
|
|
|
|
}
|
226
|
|
|
|
|
|
|
# STATIC boolean
|
227
|
|
|
|
|
|
|
sub export {
|
228
|
32
|
|
|
32
|
1
|
3905
|
my $class = $_[0];
|
229
|
32
|
|
|
|
|
50
|
my $export_to_class = $_[1];
|
230
|
|
|
|
|
|
|
|
231
|
32
|
100
|
|
|
|
116
|
return 0 if($EXPORTED->{$export_to_class});
|
232
|
20
|
|
|
|
|
48
|
$EXPORTED->{$export_to_class} = 1;
|
233
|
20
|
|
|
|
|
276
|
$class->_decorate_attribute_handler($export_to_class, "$export_to_class\::MODIFY_CODE_ATTRIBUTES");
|
234
|
20
|
|
|
|
|
62
|
return 1;
|
235
|
|
|
|
|
|
|
}
|
236
|
|
|
|
|
|
|
# STATIC void
|
237
|
|
|
|
|
|
|
sub register_helper_method {
|
238
|
4
|
|
|
4
|
1
|
45
|
my $class = $_[0];
|
239
|
4
|
|
|
|
|
8
|
my $methodname = $_[1];
|
240
|
|
|
|
|
|
|
|
241
|
4
|
|
|
|
|
15
|
$HELPER_METHODS->{$methodname} = 1;
|
242
|
4
|
|
|
|
|
513
|
return;
|
243
|
|
|
|
|
|
|
}
|
244
|
|
|
|
|
|
|
# STATIC void
|
245
|
|
|
|
|
|
|
sub _decorate_attribute_handler {
|
246
|
20
|
|
|
20
|
|
37
|
my $class = $_[0];
|
247
|
20
|
|
|
|
|
44
|
my $caller_class = $_[1];
|
248
|
20
|
|
|
|
|
31
|
my $identifier = $_[2];
|
249
|
|
|
|
|
|
|
|
250
|
5
|
|
|
5
|
|
31
|
no warnings 'redefine';
|
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
250
|
|
251
|
5
|
|
|
5
|
|
33
|
no strict 'refs';
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
2180
|
|
252
|
|
|
|
|
|
|
|
253
|
20
|
|
|
|
|
36
|
my $old = *{$identifier}{CODE};
|
|
20
|
|
|
|
|
115
|
|
254
|
20
|
|
|
|
|
63
|
*{$identifier} = sub {
|
255
|
34
|
|
|
34
|
|
26307
|
my @unknown_attributes = &_attribute_handler(@_);
|
256
|
34
|
100
|
100
|
|
|
119
|
if($old && @unknown_attributes) {
|
257
|
4
|
|
|
|
|
13
|
my $caller_class = $_[0];
|
258
|
4
|
|
|
|
|
10
|
my $sub_ref = $_[1];
|
259
|
|
|
|
|
|
|
|
260
|
4
|
|
|
|
|
17
|
@_ = ($caller_class, $sub_ref, @unknown_attributes);
|
261
|
4
|
|
|
|
|
28
|
goto &$old;
|
262
|
|
|
|
|
|
|
}
|
263
|
30
|
|
|
|
|
80
|
return @unknown_attributes;
|
264
|
20
|
|
|
|
|
108
|
};
|
265
|
20
|
|
|
|
|
47
|
return;
|
266
|
|
|
|
|
|
|
}
|
267
|
|
|
|
|
|
|
# AUTOMAGIC string()
|
268
|
|
|
|
|
|
|
sub _attribute_handler {
|
269
|
34
|
|
|
34
|
|
55
|
my $caller_class = shift(@_);
|
270
|
34
|
|
|
|
|
54
|
my $sub_ref = shift(@_);
|
271
|
34
|
|
|
|
|
75
|
my @attributes = @_;
|
272
|
|
|
|
|
|
|
|
273
|
34
|
100
|
100
|
|
|
189
|
if($LAST_ATTRIBUTE_METHOD && !$LAST_ATTRIBUTE_METHOD->{'resolved'}) {
|
274
|
29
|
|
|
|
|
93
|
my $succes = __PACKAGE__->_resolve_sub($LAST_ATTRIBUTE_METHOD);
|
275
|
29
|
50
|
|
|
|
117
|
if(!$LAST_ATTRIBUTE_METHOD->{'executed'}) {
|
276
|
29
|
|
|
|
|
126
|
my $success = __PACKAGE__->_exec_attribute($LAST_ATTRIBUTE_METHOD);
|
277
|
|
|
|
|
|
|
}
|
278
|
|
|
|
|
|
|
}
|
279
|
34
|
|
|
|
|
66
|
my @unknown_attributes = ();
|
280
|
34
|
|
|
|
|
60
|
foreach my $attribute_string (@attributes) {
|
281
|
38
|
|
|
|
|
137
|
my ($name, $data) = __PACKAGE__->_split_attribute($attribute_string);
|
282
|
38
|
|
|
|
|
82
|
my $handler = $ATT_METHODS->{$name};
|
283
|
38
|
100
|
|
|
|
91
|
if(!$handler) {
|
284
|
6
|
|
|
|
|
12
|
push(@unknown_attributes, $attribute_string);
|
285
|
6
|
|
|
|
|
18
|
next;
|
286
|
|
|
|
|
|
|
}
|
287
|
32
|
50
|
|
|
|
111
|
if($SUBS->{int($sub_ref)}) {
|
288
|
0
|
|
|
|
|
0
|
_croak("Internal failure: subroutine '$sub_ref' allways registered");
|
289
|
|
|
|
|
|
|
}
|
290
|
|
|
|
|
|
|
$LAST_ATTRIBUTE_METHOD = {
|
291
|
32
|
|
|
|
|
5473
|
'attribute' => $name,
|
292
|
|
|
|
|
|
|
'handler' => $handler,
|
293
|
|
|
|
|
|
|
'sub' => $sub_ref,
|
294
|
|
|
|
|
|
|
'class' => $caller_class,
|
295
|
|
|
|
|
|
|
'data' => $data,
|
296
|
|
|
|
|
|
|
'resolved' => 0,
|
297
|
|
|
|
|
|
|
'executed' => 0,
|
298
|
|
|
|
|
|
|
};
|
299
|
32
|
|
|
|
|
156
|
$SUBS->{int($sub_ref)} = $LAST_ATTRIBUTE_METHOD;
|
300
|
|
|
|
|
|
|
}
|
301
|
34
|
|
|
|
|
112
|
return @unknown_attributes;
|
302
|
|
|
|
|
|
|
}
|
303
|
|
|
|
|
|
|
# STATIC boolean
|
304
|
|
|
|
|
|
|
sub _resolve_sub {
|
305
|
32
|
|
|
32
|
|
55
|
my $class = $_[0];
|
306
|
32
|
|
|
|
|
55
|
my $sub_data = $_[1];
|
307
|
|
|
|
|
|
|
|
308
|
32
|
50
|
|
|
|
84
|
return 1 if($sub_data->{'resolved'});
|
309
|
|
|
|
|
|
|
|
310
|
5
|
|
|
5
|
|
32
|
no strict 'refs';
|
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
2933
|
|
311
|
|
|
|
|
|
|
|
312
|
32
|
|
|
|
|
49
|
my $symbols = \%{$sub_data->{'class'} . '::'};
|
|
32
|
|
|
|
|
95
|
|
313
|
32
|
|
|
|
|
110
|
foreach my $key (keys(%$symbols)) {
|
314
|
109
|
100
|
33
|
|
|
279
|
next if(!$symbols->{$key} || !*{$symbols->{$key}}{CODE});
|
|
109
|
|
|
|
|
465
|
|
315
|
59
|
100
|
|
|
|
121
|
if(*{$symbols->{$key}}{CODE} == $sub_data->{'sub'}) {
|
|
59
|
|
|
|
|
295
|
|
316
|
32
|
|
|
|
|
98
|
$sub_data->{'sub_name'} = $key;
|
317
|
32
|
|
|
|
|
58
|
$sub_data->{'resolved'} = 1;
|
318
|
32
|
|
|
|
|
109
|
return 1;
|
319
|
|
|
|
|
|
|
}
|
320
|
|
|
|
|
|
|
}
|
321
|
0
|
|
|
|
|
0
|
return 0;
|
322
|
|
|
|
|
|
|
}
|
323
|
|
|
|
|
|
|
# STATIC string()
|
324
|
|
|
|
|
|
|
sub _split_attribute {
|
325
|
38
|
|
|
38
|
|
53
|
my $class = $_[0];
|
326
|
38
|
|
|
|
|
166
|
my $string = $_[1];
|
327
|
|
|
|
|
|
|
|
328
|
38
|
|
|
|
|
230
|
my ($name, $data) = $string =~ m/^([^\(]*)(?:\((.*)\)|)$/i;
|
329
|
38
|
50
|
|
|
|
98
|
if(!$name) {
|
330
|
0
|
|
|
|
|
0
|
_croak("Attribute '$string' is malformed", 1);
|
331
|
|
|
|
|
|
|
}
|
332
|
38
|
|
|
|
|
104
|
return ($name, $data);
|
333
|
|
|
|
|
|
|
}
|
334
|
|
|
|
|
|
|
# STATIC sub
|
335
|
|
|
|
|
|
|
sub _exec_attribute {
|
336
|
32
|
|
|
32
|
|
45
|
my $class = $_[0];
|
337
|
32
|
|
|
|
|
47
|
my $sub_data = $_[1];
|
338
|
|
|
|
|
|
|
|
339
|
32
|
50
|
|
|
|
77
|
return 1 if($sub_data->{'executed'});
|
340
|
32
|
|
|
|
|
57
|
my $att_class = $sub_data->{'handler'}->{'class'};
|
341
|
32
|
|
|
|
|
56
|
my $att_method = $sub_data->{'handler'}->{'coderef'};
|
342
|
|
|
|
|
|
|
|
343
|
32
|
|
|
|
|
54
|
local $Carp::CarpLevel = $Carp::CarpLevel + 2;
|
344
|
32
|
50
|
|
|
|
110
|
if($att_class->$att_method($sub_data)) {
|
345
|
32
|
|
|
|
|
21535
|
$sub_data->{'executed'} = 1;
|
346
|
32
|
|
|
|
|
118
|
return 1;
|
347
|
|
|
|
|
|
|
}
|
348
|
0
|
|
|
|
|
0
|
return 0;
|
349
|
|
|
|
|
|
|
}
|
350
|
|
|
|
|
|
|
# STATIC void
|
351
|
|
|
|
|
|
|
sub run_check {
|
352
|
19
|
|
|
19
|
1
|
3461
|
my $class = $_[0];
|
353
|
|
|
|
|
|
|
|
354
|
19
|
|
|
|
|
114
|
foreach my $ref_no (keys %$SUBS) {
|
355
|
123
|
|
|
|
|
361
|
my $entry = $SUBS->{$ref_no};
|
356
|
123
|
100
|
|
|
|
331
|
if(!$entry->{'executed'}) {
|
357
|
3
|
50
|
|
|
|
16
|
if(!__PACKAGE__->_resolve_sub($entry)) {
|
358
|
0
|
|
|
|
|
0
|
_croak("Internal error: can't resolve sub '$entry->{'sub'}'");
|
359
|
|
|
|
|
|
|
}
|
360
|
3
|
50
|
|
|
|
19
|
if(!__PACKAGE__->_exec_attribute($entry)) {
|
361
|
0
|
|
|
|
|
0
|
_croak("Internal error: can't execute attribute '$entry->{'attribute'}' for sub '$entry->{'class'}->$entry->{'sub_name'}'");
|
362
|
|
|
|
|
|
|
}
|
363
|
|
|
|
|
|
|
}
|
364
|
|
|
|
|
|
|
}
|
365
|
19
|
|
|
|
|
1288
|
return;
|
366
|
|
|
|
|
|
|
}
|
367
|
|
|
|
|
|
|
|
368
|
5
|
|
|
5
|
|
31
|
no warnings 'void'; # avoid 'Too late to run CHECK/INIT block'
|
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
446
|
|
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
# AUTOMAGIC
|
371
|
|
|
|
|
|
|
CHECK {
|
372
|
5
|
|
|
5
|
|
961
|
__PACKAGE__->run_check();
|
373
|
|
|
|
|
|
|
}
|
374
|
|
|
|
|
|
|
# AUTOMAGIC
|
375
|
|
|
|
|
|
|
END {
|
376
|
5
|
|
|
5
|
|
2698
|
__PACKAGE__->run_check();
|
377
|
|
|
|
|
|
|
}
|
378
|
|
|
|
|
|
|
1;
|