line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POE::Declare::Meta; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=pod |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 NAME |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
POE::Declare::Meta - Metadata object that describes a POE::Declare class |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 DESCRIPTION |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
B objects are constructed and used internally by |
12
|
|
|
|
|
|
|
L during class construction. B objects |
13
|
|
|
|
|
|
|
are not created directly. |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Access to the meta object for a L class is via the exported |
16
|
|
|
|
|
|
|
C function. |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 METHODS |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
=cut |
21
|
|
|
|
|
|
|
|
22
|
7
|
|
|
7
|
|
155
|
use 5.008007; |
|
7
|
|
|
|
|
15
|
|
23
|
7
|
|
|
7
|
|
22
|
use strict; |
|
7
|
|
|
|
|
8
|
|
|
7
|
|
|
|
|
122
|
|
24
|
7
|
|
|
7
|
|
20
|
use warnings; |
|
7
|
|
|
|
|
6
|
|
|
7
|
|
|
|
|
141
|
|
25
|
7
|
|
|
7
|
|
24
|
use Carp (); |
|
7
|
|
|
|
|
6
|
|
|
7
|
|
|
|
|
72
|
|
26
|
7
|
|
|
7
|
|
3999
|
use File::Temp (); |
|
7
|
|
|
|
|
47380
|
|
|
7
|
|
|
|
|
170
|
|
27
|
7
|
|
|
7
|
|
42
|
use Scalar::Util (); |
|
7
|
|
|
|
|
8
|
|
|
7
|
|
|
|
|
109
|
|
28
|
7
|
|
|
7
|
|
22
|
use Params::Util (); |
|
7
|
|
|
|
|
8
|
|
|
7
|
|
|
|
|
70
|
|
29
|
7
|
|
|
7
|
|
2601
|
use Class::ISA (); |
|
7
|
|
|
|
|
11617
|
|
|
7
|
|
|
|
|
106
|
|
30
|
7
|
|
|
7
|
|
35
|
use Class::Inspector (); |
|
7
|
|
|
|
|
7
|
|
|
7
|
|
|
|
|
94
|
|
31
|
|
|
|
|
|
|
|
32
|
7
|
|
|
7
|
|
52
|
use vars qw{$VERSION $DEBUG}; |
|
7
|
|
|
|
|
8
|
|
|
7
|
|
|
|
|
298
|
|
33
|
|
|
|
|
|
|
BEGIN { |
34
|
7
|
|
|
7
|
|
10
|
$VERSION = '0.23_01'; |
35
|
7
|
|
|
|
|
98
|
$DEBUG = !! $DEBUG; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
7
|
|
|
7
|
|
26
|
use constant DEBUG => $DEBUG; |
|
7
|
|
|
|
|
6
|
|
|
7
|
|
|
|
|
390
|
|
39
|
|
|
|
|
|
|
|
40
|
7
|
|
|
7
|
|
2417
|
use POE::Declare::Meta::Slot (); |
|
7
|
|
|
|
|
12
|
|
|
7
|
|
|
|
|
109
|
|
41
|
7
|
|
|
7
|
|
2146
|
use POE::Declare::Meta::Message (); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
92
|
|
42
|
7
|
|
|
7
|
|
2008
|
use POE::Declare::Meta::Event (); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
95
|
|
43
|
7
|
|
|
7
|
|
2380
|
use POE::Declare::Meta::Timeout (); |
|
7
|
|
|
|
|
47
|
|
|
7
|
|
|
|
|
98
|
|
44
|
7
|
|
|
7
|
|
28
|
use POE::Declare::Meta::Attribute (); |
|
7
|
|
|
|
|
7
|
|
|
7
|
|
|
|
|
66
|
|
45
|
7
|
|
|
7
|
|
2152
|
use POE::Declare::Meta::Internal (); |
|
7
|
|
|
|
|
11
|
|
|
7
|
|
|
|
|
91
|
|
46
|
7
|
|
|
7
|
|
26
|
use POE::Declare::Meta::Param (); |
|
7
|
|
|
|
|
7
|
|
|
7
|
|
|
|
|
144
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
use Class::XSAccessor |
49
|
7
|
|
|
|
|
50
|
getters => { |
50
|
|
|
|
|
|
|
name => 'name', |
51
|
|
|
|
|
|
|
alias => 'alias', |
52
|
|
|
|
|
|
|
sequence => 'sequence', |
53
|
|
|
|
|
|
|
compiled => 'compiled', |
54
|
7
|
|
|
7
|
|
17
|
}; |
|
7
|
|
|
|
|
8
|
|
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
##################################################################### |
61
|
|
|
|
|
|
|
# Constructor |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub new { |
64
|
0
|
|
|
0
|
0
|
|
my $class = shift; |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
# The name of the class |
67
|
0
|
|
|
|
|
|
my $name = shift; |
68
|
0
|
0
|
|
|
|
|
unless ( Params::Util::_CLASS($name) ) { |
69
|
0
|
|
|
|
|
|
Carp::croak("Invalid class name '$name'"); |
70
|
|
|
|
|
|
|
} |
71
|
0
|
0
|
|
|
|
|
unless ( Class::Inspector->loaded($name) ) { |
72
|
0
|
|
|
|
|
|
Carp::croak("Class $name is not loaded"); |
73
|
|
|
|
|
|
|
} |
74
|
0
|
0
|
|
|
|
|
unless ( $name->isa('POE::Declare::Object') ) { |
75
|
0
|
|
|
|
|
|
Carp::croak("Class $name is not a POE::Declare::Object subclass"); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
# Create the object |
79
|
0
|
|
|
|
|
|
my $self = bless { |
80
|
|
|
|
|
|
|
name => $name, |
81
|
|
|
|
|
|
|
alias => $name, |
82
|
|
|
|
|
|
|
sequence => 0, |
83
|
|
|
|
|
|
|
attr => { }, |
84
|
|
|
|
|
|
|
}, $class; |
85
|
|
|
|
|
|
|
|
86
|
0
|
|
|
|
|
|
$self; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
##################################################################### |
94
|
|
|
|
|
|
|
# Accessors |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=pod |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
=head2 name |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
The C accessor returns the name of the class for this meta instance. |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=cut |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# sub name { |
105
|
|
|
|
|
|
|
# $_[0]->{name}; |
106
|
|
|
|
|
|
|
# } |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=pod |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
=head2 alias |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
The C accessor returns the alias root string that will be used for |
113
|
|
|
|
|
|
|
objects that are created of this type. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
Normally this will be identical to the class C but may be changed |
116
|
|
|
|
|
|
|
at constructor time. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=cut |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
# sub alias { |
121
|
|
|
|
|
|
|
# $_[0]->{alias}; |
122
|
|
|
|
|
|
|
# } |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=pod |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
=head2 sequence |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
Because each object has its own L, each session also needs |
129
|
|
|
|
|
|
|
its own session alias, and the session alias is derived from a combination |
130
|
|
|
|
|
|
|
of the C method an an incrementing C value. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
The C accessor returns the most recently requested value from the |
133
|
|
|
|
|
|
|
sequence. As with sequence in SQL, not all values pulled from the sequence |
134
|
|
|
|
|
|
|
will necesarily be used in an object, and objects will not necesarily have |
135
|
|
|
|
|
|
|
incrementing sequence values. |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=cut |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
# sub sequence { |
140
|
|
|
|
|
|
|
# $_[0]->{sequence}; |
141
|
|
|
|
|
|
|
# } |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
##################################################################### |
148
|
|
|
|
|
|
|
# Methods |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
=pod |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=head2 next_alias |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
The C method generates and returns a new session alias, |
155
|
|
|
|
|
|
|
by taking the C base string and appending an incremented |
156
|
|
|
|
|
|
|
C value. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
The typical alias string returned will look something like |
159
|
|
|
|
|
|
|
C<'My::Class.123'>. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=cut |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
sub next_alias { |
164
|
0
|
|
|
0
|
1
|
|
$_[0]->{alias} . '.' . ++$_[0]->{sequence}; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=pod |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
=head2 super_path |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
The C method is provided as a convenience, and returns a list |
172
|
|
|
|
|
|
|
of the inheritance path for the class. |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
It is equivalent to C. |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=cut |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub super_path { |
179
|
0
|
|
|
0
|
1
|
|
Class::ISA::self_and_super_path( $_[0]->name ); |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=pod |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=head2 attr |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
my $attribute = My::Class->meta->attr('foo'); |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
The C method is used to get a single named attribute meta object |
189
|
|
|
|
|
|
|
within the class meta object. |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
Returns a L object or C if no such |
192
|
|
|
|
|
|
|
named attribute exists. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=cut |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
sub attr { |
197
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
198
|
0
|
|
|
|
|
|
my $name = shift; |
199
|
0
|
|
|
|
|
|
foreach my $c ( $self->super_path ) { |
200
|
0
|
0
|
|
|
|
|
my $meta = $POE::Declare::META{$c} or next; |
201
|
0
|
0
|
|
|
|
|
my $attr = $meta->{attr}->{$name} or next; |
202
|
0
|
|
|
|
|
|
return $attr; |
203
|
|
|
|
|
|
|
} |
204
|
0
|
|
|
|
|
|
return undef; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
# Fetch all named attributes (from this or parents) |
208
|
|
|
|
|
|
|
sub attrs { |
209
|
0
|
|
|
0
|
0
|
|
my $self = shift; |
210
|
0
|
|
|
|
|
|
my %hash = (); |
211
|
0
|
|
|
|
|
|
foreach my $c ( $self->super_path ) { |
212
|
0
|
0
|
|
|
|
|
my $meta = $POE::Declare::META{$c} or next; |
213
|
0
|
|
|
|
|
|
my $attr = $meta->{attr}; |
214
|
0
|
|
|
|
|
|
foreach ( keys %$attr ) { |
215
|
0
|
|
|
|
|
|
$hash{$_} = $attr->{$_}; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
} |
218
|
0
|
|
|
|
|
|
return values %hash; |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
##################################################################### |
226
|
|
|
|
|
|
|
# Compilation |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
sub _compile { |
229
|
0
|
|
|
0
|
|
|
my $self = shift; |
230
|
0
|
|
|
|
|
|
my $name = $self->name; |
231
|
0
|
|
|
|
|
|
my $attr = $self->{attr}; |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
# Go over all our methods, and add any required events |
234
|
0
|
|
|
|
|
|
my $methods = Class::Inspector->methods($name, 'expanded'); |
235
|
0
|
|
|
|
|
|
foreach my $method ( @$methods ) { |
236
|
0
|
|
|
|
|
|
my $mname = $method->[2]; |
237
|
0
|
|
|
|
|
|
my $mcode = $method->[3]; |
238
|
0
|
|
|
|
|
|
my $maddr = Scalar::Util::refaddr($mcode); |
239
|
0
|
0
|
|
|
|
|
my $mevent = $POE::Declare::EVENT{$maddr} or next; |
240
|
0
|
|
|
|
|
|
my $mattr = $self->attr($mname); |
241
|
0
|
0
|
|
|
|
|
if ( $mattr ) { |
242
|
|
|
|
|
|
|
# Make sure the existing attribute is an event |
243
|
0
|
0
|
|
|
|
|
next if $mattr->isa('POE::Declare::Meta::Event'); |
244
|
0
|
|
|
|
|
|
Carp::croak("Event '$mname' in $name clashes with non-event in parent class"); |
245
|
0
|
|
|
|
|
|
next; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# Add an attribute for the event |
249
|
0
|
|
|
|
|
|
my $class = $mevent->[0]; |
250
|
0
|
|
|
|
|
|
my @param = @$mevent[1..$#$mevent]; |
251
|
0
|
|
|
|
|
|
$self->{attr}->{$mname} = $class->new( |
252
|
|
|
|
|
|
|
name => $mname, |
253
|
|
|
|
|
|
|
@param, |
254
|
|
|
|
|
|
|
); |
255
|
|
|
|
|
|
|
} |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# Get all the package fragments |
258
|
|
|
|
|
|
|
my $code = join "\n", ( |
259
|
|
|
|
|
|
|
"package " . $self->name . ";", |
260
|
|
|
|
|
|
|
"sub meta () { \$POE::Declare::META{'$name'} }", |
261
|
|
|
|
|
|
|
map { |
262
|
0
|
|
|
|
|
|
$attr->{$_}->_compile |
|
0
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
} sort keys %$attr |
264
|
|
|
|
|
|
|
); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
# Load the code |
267
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
268
|
|
|
|
|
|
|
# Compile the combined code via a temp file |
269
|
|
|
|
|
|
|
my ($fh, $filename) = File::Temp::tempfile(); |
270
|
|
|
|
|
|
|
$fh->print("$code\n\n1;\n"); |
271
|
|
|
|
|
|
|
close $fh; |
272
|
|
|
|
|
|
|
require $filename; |
273
|
|
|
|
|
|
|
unlink $filename; |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
# Print the debugging output |
276
|
|
|
|
|
|
|
my @trace = map { |
277
|
|
|
|
|
|
|
s/\s*[{;]$//; |
278
|
|
|
|
|
|
|
s/^s/ s/; |
279
|
|
|
|
|
|
|
s/^p/\np/; |
280
|
|
|
|
|
|
|
"$_\n" |
281
|
|
|
|
|
|
|
} grep { |
282
|
|
|
|
|
|
|
/^(?:package|sub)\b/ |
283
|
|
|
|
|
|
|
} split /\n/, $code; |
284
|
|
|
|
|
|
|
print STDERR @trace, "\n$name code saved as $filename\n\n"; |
285
|
|
|
|
|
|
|
} else { |
286
|
0
|
|
|
|
|
|
eval("$code\n\n1;\n"); |
287
|
0
|
0
|
|
|
|
|
die $@ if $@; |
288
|
0
|
0
|
|
|
|
|
Carp::croak("Failed to compile code for $name") if $@; |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
return ( |
292
|
0
|
|
|
|
|
|
$self->{compiled} = 1 |
293
|
|
|
|
|
|
|
); |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# sub compiled { |
297
|
|
|
|
|
|
|
# $_[0]->{compiled}; |
298
|
|
|
|
|
|
|
# } |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
##################################################################### |
305
|
|
|
|
|
|
|
# Run-Time Support Methods |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
# Resolve the inline states for a class |
308
|
|
|
|
|
|
|
sub _package_states { |
309
|
0
|
|
|
0
|
|
|
my $self = shift; |
310
|
0
|
0
|
|
|
|
|
unless ( exists $self->{_package_states} ) { |
311
|
|
|
|
|
|
|
# Cache for speed reasons |
312
|
|
|
|
|
|
|
$self->{_package_states} = [ |
313
|
|
|
|
|
|
|
sort map { |
314
|
0
|
|
|
|
|
|
$_->name |
315
|
|
|
|
|
|
|
} grep { |
316
|
0
|
|
|
|
|
|
$_->isa('POE::Declare::Meta::Event') |
|
0
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
} $self->attrs |
318
|
|
|
|
|
|
|
]; |
319
|
|
|
|
|
|
|
} |
320
|
0
|
0
|
|
|
|
|
if ( wantarray ) { |
321
|
0
|
|
|
|
|
|
return @{$self->{_package_states}}; |
|
0
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
} else { |
323
|
0
|
|
|
|
|
|
return $self->{_package_states}; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# Resolve the parameter list |
328
|
|
|
|
|
|
|
sub _params { |
329
|
0
|
|
|
0
|
|
|
my $self = shift; |
330
|
0
|
0
|
|
|
|
|
unless ( exists $self->{_params} ) { |
331
|
|
|
|
|
|
|
# Cache for speed reasons |
332
|
|
|
|
|
|
|
$self->{_params} = [ |
333
|
|
|
|
|
|
|
sort map { |
334
|
0
|
|
|
|
|
|
$_->name |
335
|
|
|
|
|
|
|
} grep { |
336
|
0
|
|
|
|
|
|
$_->isa('POE::Declare::Meta::Param') |
|
0
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
} $self->attrs |
338
|
|
|
|
|
|
|
]; |
339
|
|
|
|
|
|
|
} |
340
|
0
|
0
|
|
|
|
|
if ( wantarray ) { |
341
|
0
|
|
|
|
|
|
return @{$self->{_params}}; |
|
0
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
} else { |
343
|
0
|
|
|
|
|
|
return $self->{_params}; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
} |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
# Resolve the message list |
348
|
|
|
|
|
|
|
sub _messages { |
349
|
0
|
|
|
0
|
|
|
my $self = shift; |
350
|
0
|
0
|
|
|
|
|
unless ( exists $self->{_messages} ) { |
351
|
|
|
|
|
|
|
# Cache for speed reasons |
352
|
|
|
|
|
|
|
$self->{_messages} = [ |
353
|
|
|
|
|
|
|
sort map { |
354
|
0
|
|
|
|
|
|
$_->name |
355
|
|
|
|
|
|
|
} grep { |
356
|
0
|
|
|
|
|
|
$_->isa('POE::Declare::Meta::Message') |
|
0
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
} $self->attrs |
358
|
|
|
|
|
|
|
]; |
359
|
|
|
|
|
|
|
} |
360
|
0
|
0
|
|
|
|
|
if ( wantarray ) { |
361
|
0
|
|
|
|
|
|
return @{$self->{_messages}}; |
|
0
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
} else { |
363
|
0
|
|
|
|
|
|
return $self->{_messages}; |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
1; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
=pod |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
=head1 SUPPORT |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
Bugs should be always be reported via the CPAN bug tracker at |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
L |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
For other issues, or commercial enhancement or support, contact the author. |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
=head1 AUTHORS |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
Adam Kennedy Eadamk@cpan.orgE |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
=head1 SEE ALSO |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
L |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=head1 COPYRIGHT |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
Copyright 2006 - 2009 Adam Kennedy. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
This program is free software; you can redistribute |
392
|
|
|
|
|
|
|
it and/or modify it under the same terms as Perl itself. |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
The full text of the license can be found in the |
395
|
|
|
|
|
|
|
LICENSE file included with this module. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=cut |