line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Anansi::Library; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
=head1 NAME |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
Anansi::Library - A base module definition for object functionality extension. |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
=head1 SYNOPSIS |
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
# Note: As 'base' needs a module file, this package must be declared in 'LibraryExample.pm'. |
11
|
|
|
|
|
|
|
package LibraryExample; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
use base qw(Anansi::Library); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub libraryExample { |
16
|
|
|
|
|
|
|
my ($self, %parameters) = @_; |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
1; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
# Note: This package should be declared in 'ClassExample.pm'. |
22
|
|
|
|
|
|
|
package ClassExample; |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
use base qw(Anansi::Class LibraryExample); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub classExample { |
27
|
|
|
|
|
|
|
my ($self, %parameters) = @_; |
28
|
|
|
|
|
|
|
$self->libraryExample(); |
29
|
|
|
|
|
|
|
$self->LibraryExample::libraryExample(); |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
1; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
=head1 DESCRIPTION |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
This is a base module definition that manages the functionality extension of |
37
|
|
|
|
|
|
|
module object instances. |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
=cut |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
our $VERSION = '0.03'; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my $LIBRARY = {}; |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 METHODS |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
=cut |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head2 abstractClosure |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
my $CLOSURE = Anansi::Library->abstractClosure( |
55
|
|
|
|
|
|
|
'Some::Namespace', |
56
|
|
|
|
|
|
|
'someKey' => 'some data', |
57
|
|
|
|
|
|
|
'anotherKey' => 'Subroutine::Namespace', |
58
|
|
|
|
|
|
|
'yetAnotherKey' => Namespace::someSubroutine, |
59
|
|
|
|
|
|
|
); |
60
|
|
|
|
|
|
|
$CLOSURE->anotherKey(); |
61
|
|
|
|
|
|
|
$CLOSURE->yetAnotherKey(); |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub Subroutine::Namespace { |
64
|
|
|
|
|
|
|
my ($self, $closure, %parameters) = @_; |
65
|
|
|
|
|
|
|
my $abc = ${$closure}{abc} || 'something'; |
66
|
|
|
|
|
|
|
${$closure}{def} = 'anything'; |
67
|
|
|
|
|
|
|
} |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=over 4 |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=item class I<(Blessed Hash B String, Required)> |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
Either an object of this namespace or this module's namespace. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item abstract I<(String, Required)> |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
The namespace to associate with the closure's encapsulating object. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
=item parameters I<(Hash, Optional)> |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
Named parameters where either the key is the name of a variable stored within |
82
|
|
|
|
|
|
|
the closure and the value is it's data or when the value is a subroutine the key |
83
|
|
|
|
|
|
|
is the name of a generated method of the closure's encapsulating object that |
84
|
|
|
|
|
|
|
runs the subroutine and passes it a reference to the closure. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=back |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
Creates both an anonymous hash to act as a closure variable and a blessed object |
89
|
|
|
|
|
|
|
as the closure's encapsulating accessor. Supplied data is either stored within |
90
|
|
|
|
|
|
|
the closure using the key as the name or in the case of a subroutine, accessed |
91
|
|
|
|
|
|
|
by an auto-generated method of that name. Closure is achieved by passing a |
92
|
|
|
|
|
|
|
reference to the anonymous hash to the supplied subroutines via the |
93
|
|
|
|
|
|
|
auto-generated methods. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=cut |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub abstractClosure { |
99
|
0
|
|
|
0
|
1
|
|
my ($class, $abstract, %parameters) = @_; |
100
|
0
|
0
|
|
|
|
|
return if(ref($abstract) !~ /^$/); |
101
|
0
|
0
|
|
|
|
|
return if($abstract !~ /[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)+$/); |
102
|
0
|
|
|
|
|
|
my $ABSTRACT = { |
103
|
|
|
|
|
|
|
NAMESPACE => $abstract, |
104
|
|
|
|
|
|
|
}; |
105
|
0
|
|
|
|
|
|
my $CLOSURE = { |
106
|
|
|
|
|
|
|
}; |
107
|
0
|
|
|
|
|
|
foreach my $key (keys(%parameters)) { |
108
|
0
|
0
|
|
|
|
|
next if(ref($key) !~ /^$/); |
109
|
0
|
0
|
|
|
|
|
next if($key !~ /^[a-zA-Z_]*[a-zA-Z0-9_]+$/); |
110
|
0
|
0
|
|
|
|
|
next if('NAMESPACE' eq $key); |
111
|
0
|
0
|
|
|
|
|
if(ref($parameters{$key}) =~ /^CODE$/i) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
112
|
0
|
|
|
|
|
|
*{$abstract.'::'.$key} = sub { |
113
|
0
|
|
|
0
|
|
|
my ($self, @PARAMETERS) = @_; |
114
|
0
|
|
|
|
|
|
return &{$parameters{$key}}($self, $CLOSURE, (@PARAMETERS)); |
|
0
|
|
|
|
|
|
|
115
|
0
|
|
|
|
|
|
}; |
116
|
|
|
|
|
|
|
} elsif(ref($parameters{$key}) !~ /^$/i) { |
117
|
0
|
|
|
|
|
|
${$CLOSURE}{$key} = $parameters{$key}; |
|
0
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
} elsif($parameters{$key} =~ /^[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)+$/) { |
119
|
0
|
0
|
|
|
|
|
if(exists(&{$parameters{$key}})) { |
|
0
|
|
|
|
|
|
|
120
|
0
|
|
|
|
|
|
*{$abstract.'::'.$key} = sub { |
121
|
0
|
|
|
0
|
|
|
my ($self, @PARAMETERS) = @_; |
122
|
0
|
|
|
|
|
|
return &{\&{$parameters{$key}}}($self, $CLOSURE, (@PARAMETERS)); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
123
|
0
|
|
|
|
|
|
}; |
124
|
|
|
|
|
|
|
} else { |
125
|
0
|
|
|
|
|
|
${$CLOSURE}{$key} = $parameters{$key} |
|
0
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
} else { |
128
|
0
|
|
|
|
|
|
${$CLOSURE}{$key} = $parameters{$key}; |
|
0
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
} |
131
|
0
|
|
|
|
|
|
return bless($ABSTRACT, $abstract); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
=head2 abstractObject |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
my $OBJECT = Anansi::Library->abstractObject( |
138
|
|
|
|
|
|
|
'Some::Namespace', |
139
|
|
|
|
|
|
|
'someKey' => 'some data', |
140
|
|
|
|
|
|
|
'anotherKey' => 'Subroutine::Namespace', |
141
|
|
|
|
|
|
|
'yetAnotherKey' => Namespace::someSubroutine, |
142
|
|
|
|
|
|
|
); |
143
|
|
|
|
|
|
|
$OBJECT->anotherKey(); |
144
|
|
|
|
|
|
|
$OBJECT->yetAnotherKey(); |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub Subroutine::Namespace { |
147
|
|
|
|
|
|
|
my ($self, %parameters) = @_; |
148
|
|
|
|
|
|
|
my $abc = $self->{abc} || 'something'; |
149
|
|
|
|
|
|
|
$self->{def} = 'anything'; |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
=over 4 |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
=item class I<(Blessed Hash B String, Required)> |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Either an object of this namespace or this module's namespace. |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
=item abstract I<(String, Required)> |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
The namespace to associate with the object. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
=item parameters I<(Hash, Required)> |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
Named parameters where either the key is the name of a variable stored within |
165
|
|
|
|
|
|
|
the object and the value is it's data or when the value is a subroutine the key |
166
|
|
|
|
|
|
|
is the name of a namespace method. |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
=back |
169
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
Creates a blessed object. Supplied data is either stored within the object or |
171
|
|
|
|
|
|
|
in the case of a subroutine as a namespace method of that name. |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
=cut |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
sub abstractObject { |
177
|
0
|
|
|
0
|
1
|
|
my ($class, $abstract, %parameters) = @_; |
178
|
0
|
0
|
|
|
|
|
return if(ref($abstract) !~ /^$/); |
179
|
0
|
0
|
|
|
|
|
return if($abstract !~ /[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)+$/); |
180
|
0
|
|
|
|
|
|
my $ABSTRACT = { |
181
|
|
|
|
|
|
|
NAMESPACE => $abstract, |
182
|
|
|
|
|
|
|
}; |
183
|
0
|
|
|
|
|
|
foreach my $key (keys(%parameters)) { |
184
|
0
|
0
|
|
|
|
|
next if(ref($key) !~ /^$/); |
185
|
0
|
0
|
|
|
|
|
next if($key !~ /^[a-zA-Z_]*[a-zA-Z0-9_]+$/); |
186
|
0
|
0
|
|
|
|
|
next if('NAMESPACE' eq $key); |
187
|
0
|
0
|
|
|
|
|
if(ref($parameters{$key}) =~ /^CODE$/i) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
188
|
0
|
|
|
|
|
|
*{$abstract.'::'.$key} = $parameters{$key}; |
|
0
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
} elsif(ref($parameters{$key}) !~ /^$/i) { |
190
|
0
|
|
|
|
|
|
$ABSTRACT->{$key} = $parameters{$key}; |
191
|
|
|
|
|
|
|
} elsif($parameters{$key} =~ /^[a-zA-Z]+[a-zA-Z0-9_]*(::[a-zA-Z]+[a-zA-Z0-9_]*)+$/) { |
192
|
0
|
0
|
|
|
|
|
if(exists(&{$parameters{$key}})) { |
|
0
|
|
|
|
|
|
|
193
|
0
|
|
|
|
|
|
*{$abstract.'::'.$key} = *{$parameters{$key}}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
} else { |
195
|
0
|
|
|
|
|
|
$ABSTRACT->{$key} = $parameters{$key} |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
} else { |
198
|
0
|
|
|
|
|
|
$ABSTRACT->{$key} = $parameters{$key}; |
199
|
|
|
|
|
|
|
} |
200
|
|
|
|
|
|
|
} |
201
|
0
|
|
|
|
|
|
return bless($ABSTRACT, $abstract); |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=head2 hasAncestor |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
my $MODULE_ARRAY = $OBJECT->hasAncestor(); |
208
|
|
|
|
|
|
|
if(defined($MODULE_ARRAY)); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
if(1 == $OBJECT->hasAncestor( |
211
|
|
|
|
|
|
|
'Some::Module', |
212
|
|
|
|
|
|
|
'Another::Module', |
213
|
|
|
|
|
|
|
'Etc' |
214
|
|
|
|
|
|
|
)); |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=over 4 |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
=item self I<(Blessed Hash, Required)> |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
An object of this namespace. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item name I<(Array B String, Optional)> |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
A namespace or an array of namespaces. |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=back |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
Either returns an array of all the loaded modules that the object inherits from |
229
|
|
|
|
|
|
|
or whether the object inherits from all of the specified loaded modules with a |
230
|
|
|
|
|
|
|
B<1> I<(one)> for yes and B<0> I<(zero)> for no. |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=cut |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub hasAncestor { |
236
|
0
|
0
|
|
0
|
1
|
|
return if(0 == scalar(@_)); |
237
|
0
|
|
|
|
|
|
my $self = shift(@_); |
238
|
0
|
0
|
|
|
|
|
return if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i); |
239
|
0
|
|
|
|
|
|
my %modules; |
240
|
0
|
|
|
|
|
|
while(my ($name, $value) = each(%INC)) { |
241
|
0
|
0
|
|
|
|
|
next if($name !~ /\.pm$/); |
242
|
0
|
|
|
|
|
|
$name =~ s/\.pm//; |
243
|
0
|
0
|
|
|
|
|
$name =~ s/\//::/g if($name =~ /\//); |
244
|
0
|
0
|
|
|
|
|
next if(!$self->isa($name)); |
245
|
0
|
0
|
|
|
|
|
next if($self eq $name); |
246
|
0
|
|
|
|
|
|
$modules{$name} = 1; |
247
|
|
|
|
|
|
|
} |
248
|
0
|
0
|
|
|
|
|
if(0 == scalar(@_)) { |
249
|
0
|
0
|
|
|
|
|
return [( keys(%modules) )] if(0 < scalar(keys(%modules))); |
250
|
0
|
|
|
|
|
|
return; |
251
|
|
|
|
|
|
|
} |
252
|
0
|
|
|
|
|
|
while(0 < scalar(@_)) { |
253
|
0
|
|
|
|
|
|
my $name = shift(@_); |
254
|
0
|
0
|
|
|
|
|
return 0 if(ref($name) !~ /^$/); |
255
|
0
|
0
|
|
|
|
|
return 0 if(!defined($modules{$name})); |
256
|
|
|
|
|
|
|
} |
257
|
0
|
|
|
|
|
|
return 1; |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head2 hasDescendant |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
my $MODULE_ARRAY = $OBJECT->hasDescendant(); |
264
|
|
|
|
|
|
|
if(defined($MODULE_ARRAY)); |
265
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
if(1 == $OBJECT->hasDescendant('Some::Module', 'Another::Module', 'Etc')); |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
=over 4 |
269
|
|
|
|
|
|
|
|
270
|
|
|
|
|
|
|
=item self I<(Blessed Hash, Required)> |
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
An object of this namespace. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=item name I<(Array B String, Optional)> |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
A namespace or an array of namespaces. |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
=back |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
Either returns an array of all the loaded modules that the object is inherited |
281
|
|
|
|
|
|
|
from or whether the object is inherited from all of the specified loaded |
282
|
|
|
|
|
|
|
modules with a B<1> I<(one)> for yes and B<0> I<(zero)> for no. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
=cut |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub hasDescendant { |
288
|
0
|
0
|
|
0
|
1
|
|
return if(0 == scalar(@_)); |
289
|
0
|
|
|
|
|
|
my $self = shift(@_); |
290
|
0
|
0
|
|
|
|
|
return if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i); |
291
|
0
|
|
|
|
|
|
my %modules; |
292
|
0
|
|
|
|
|
|
while(my ($name, $value) = each(%INC)) { |
293
|
0
|
0
|
|
|
|
|
next if($name !~ /\.pm$/); |
294
|
0
|
|
|
|
|
|
$name =~ s/\.pm//; |
295
|
0
|
0
|
|
|
|
|
$name =~ s/\//::/g if($name =~ /\//); |
296
|
0
|
0
|
|
|
|
|
next if(!$name->isa($self)); |
297
|
0
|
0
|
|
|
|
|
next if($self eq $name); |
298
|
0
|
|
|
|
|
|
$modules{$name} = 1; |
299
|
|
|
|
|
|
|
} |
300
|
0
|
0
|
|
|
|
|
if(0 == scalar(@_)) { |
301
|
0
|
0
|
|
|
|
|
return [( keys(%modules) )] if(0 < scalar(keys(%modules))); |
302
|
0
|
|
|
|
|
|
return; |
303
|
|
|
|
|
|
|
} |
304
|
0
|
|
|
|
|
|
while(0 < scalar(@_)) { |
305
|
0
|
|
|
|
|
|
my $name = shift(@_); |
306
|
0
|
0
|
|
|
|
|
return 0 if(ref($name) !~ /^$/); |
307
|
0
|
0
|
|
|
|
|
return 0 if(!defined($modules{$name})); |
308
|
|
|
|
|
|
|
} |
309
|
0
|
|
|
|
|
|
return 1; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=head2 hasLoaded |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
my $MODULE_ARRAY = $OBJECT->hasLoaded(); |
316
|
|
|
|
|
|
|
if(defined($MODULE_ARRAY)); |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
my $MODULE_ARRAY = Anansi::Library->hasLoaded(); |
319
|
|
|
|
|
|
|
if(defined($MODULE_ARRAY)); |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
if(1 == $OBJECT->hasLoaded( |
322
|
|
|
|
|
|
|
'Some::Module', |
323
|
|
|
|
|
|
|
'Another::Module', |
324
|
|
|
|
|
|
|
'Etc' |
325
|
|
|
|
|
|
|
)); |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
if(1 == Anansi::Library->hasLoaded( |
328
|
|
|
|
|
|
|
'Some::Module', |
329
|
|
|
|
|
|
|
'Another::Module', |
330
|
|
|
|
|
|
|
'Etc' |
331
|
|
|
|
|
|
|
)); |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=over 4 |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=item self I<(Blessed Hash, Required)> |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
An object of this namespace. |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=item name I<(Array B String, Optional)> |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
A namespace or an array of namespaces. |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=back |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Either returns an array of all the loaded modules or whether all of the |
346
|
|
|
|
|
|
|
specified modules have been loaded with a B<1> I<(one)> for yes and B<0> |
347
|
|
|
|
|
|
|
I<(zero)> for no. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=cut |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
sub hasLoaded { |
353
|
0
|
0
|
|
0
|
1
|
|
return if(0 == scalar(@_)); |
354
|
0
|
|
|
|
|
|
my $self = shift(@_); |
355
|
0
|
0
|
|
|
|
|
return if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i); |
356
|
0
|
|
|
|
|
|
my %modules; |
357
|
0
|
|
|
|
|
|
while(my ($name, $value) = each(%INC)) { |
358
|
0
|
0
|
|
|
|
|
next if($name !~ /\.pm$/); |
359
|
0
|
|
|
|
|
|
$name =~ s/\.pm//; |
360
|
0
|
0
|
|
|
|
|
$name =~ s/\//::/g if($name =~ /\//); |
361
|
0
|
|
|
|
|
|
$modules{$name} = 1; |
362
|
|
|
|
|
|
|
} |
363
|
0
|
0
|
|
|
|
|
if(0 == scalar(@_)) { |
364
|
0
|
0
|
|
|
|
|
return [( keys(%modules) )] if(0 < scalar(keys(%modules))); |
365
|
0
|
|
|
|
|
|
return; |
366
|
|
|
|
|
|
|
} |
367
|
0
|
|
|
|
|
|
while(0 < scalar(@_)) { |
368
|
0
|
|
|
|
|
|
my $name = shift(@_); |
369
|
0
|
0
|
|
|
|
|
return 0 if(ref($name) !~ /^$/); |
370
|
0
|
0
|
|
|
|
|
return 0 if(!defined($modules{$name})); |
371
|
|
|
|
|
|
|
} |
372
|
0
|
|
|
|
|
|
return 1; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=begin comment |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
################################################################################ |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=head2 hasParameter |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
my $RESULT = Anansi::Library->hasParameter( |
383
|
|
|
|
|
|
|
EXPECTED => [ |
384
|
|
|
|
|
|
|
{ |
385
|
|
|
|
|
|
|
SOME_VALUE => { |
386
|
|
|
|
|
|
|
REQUIREMENT => 'OPTIONAL', |
387
|
|
|
|
|
|
|
VALUE => [2,4,6,8,10] |
388
|
|
|
|
|
|
|
}, |
389
|
|
|
|
|
|
|
ANOTHER_VALUE => { |
390
|
|
|
|
|
|
|
VALUE => 24 |
391
|
|
|
|
|
|
|
}, |
392
|
|
|
|
|
|
|
ETC => { |
393
|
|
|
|
|
|
|
REQUIREMENT => 'OPTIONAL' |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
} |
396
|
|
|
|
|
|
|
], |
397
|
|
|
|
|
|
|
SUPPLIED => { |
398
|
|
|
|
|
|
|
SOME_VALUE => 3, |
399
|
|
|
|
|
|
|
ANOTHER_VALUE => 15 |
400
|
|
|
|
|
|
|
} |
401
|
|
|
|
|
|
|
); |
402
|
|
|
|
|
|
|
if(-1 == $RESULT) { |
403
|
|
|
|
|
|
|
} elsif(0 == $RESULT || 1 == $RESULT || 2 == $RESULT) { |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
Determines whether the contents of SUPPLIED matches a pattern set out within |
407
|
|
|
|
|
|
|
EXPECTED. EXPECTED is either a HASH or an ARRAY of HASHES with each HASH |
408
|
|
|
|
|
|
|
containing a number of keys that mirror the keys contained within the SUPPLIED |
409
|
|
|
|
|
|
|
HASH. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
#=cut |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
sub hasParameter { |
415
|
|
|
|
|
|
|
my ($self, %parameters) = @_; |
416
|
|
|
|
|
|
|
return -1 if(!defined($parameters{EXPECTED})); |
417
|
|
|
|
|
|
|
return -1 if(!defined($parameters{SUPPLIED})); |
418
|
|
|
|
|
|
|
return -1 if(ref($parameters{SUPPLIED}) !~ /^HASH$/i); |
419
|
|
|
|
|
|
|
my @expected; |
420
|
|
|
|
|
|
|
if(ref($parameters{EXPECTED}) =~ /^ARRAY$/i) { |
421
|
|
|
|
|
|
|
@expected = (@{$parameters{EXPECTED}}); |
422
|
|
|
|
|
|
|
} elsif(ref($parameters{EXPECTED}) =~ /^HASH$/i) { |
423
|
|
|
|
|
|
|
@expected = ($parameters{EXPECTED}); |
424
|
|
|
|
|
|
|
} else { |
425
|
|
|
|
|
|
|
return -1; |
426
|
|
|
|
|
|
|
} |
427
|
|
|
|
|
|
|
my $valid = -1; |
428
|
|
|
|
|
|
|
for(my $index = 0; $index < scalar(@expected); $index++) { |
429
|
|
|
|
|
|
|
next if(ref($expected[$index]) !~ /^HASH$/i); |
430
|
|
|
|
|
|
|
$match = 1; |
431
|
|
|
|
|
|
|
while(my ($suppliedKey, $suppliedValue) = each(%{$parameters{SUPPLIED}})) { |
432
|
|
|
|
|
|
|
if(!defined(%{$expected[$index]}->{$suppliedKey})) { |
433
|
|
|
|
|
|
|
$match = 0; |
434
|
|
|
|
|
|
|
last; |
435
|
|
|
|
|
|
|
} |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
if($match) { |
438
|
|
|
|
|
|
|
$valid = $index; |
439
|
|
|
|
|
|
|
last; |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
$match = 1; |
442
|
|
|
|
|
|
|
while(my ($expectedKey, $expectedValue) = each(%{$expected[$index]})) { |
443
|
|
|
|
|
|
|
next if(ref($expectedKey) !~ /^$/); |
444
|
|
|
|
|
|
|
next if(ref($expectedValue) !~ /^HASH$/i); |
445
|
|
|
|
|
|
|
my $required = 1; |
446
|
|
|
|
|
|
|
if(!defined($expectedValue->{REQUIREMENT})) { |
447
|
|
|
|
|
|
|
} elsif(ref($expectedValue->{REQUIREMENT}) !~ /^$/) { |
448
|
|
|
|
|
|
|
} elsif($expectedValue->{REQUIREMENT} =~ /^OPTIONAL$/i) { |
449
|
|
|
|
|
|
|
$required = 0 if(!defined(%{$parameters{SUPPLIED}}->{$expectedKey})); |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
if($required) { |
452
|
|
|
|
|
|
|
next if(!defined($expectedValue->{VALUE})); |
453
|
|
|
|
|
|
|
my @expectedValues; |
454
|
|
|
|
|
|
|
if(ref($expectedValue->{VALUE}) =~ /^ARRAY$/i) { |
455
|
|
|
|
|
|
|
@expectedValues = [(@{$expectedValue->{VALUE}})]; |
456
|
|
|
|
|
|
|
} elsif(ref($expectedValue->{VALUE}) =~ /^HASH$/i) { |
457
|
|
|
|
|
|
|
@expectedValues = [$expectedValue->{VALUE}]; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
my $valued; |
460
|
|
|
|
|
|
|
if(0 < scalar(@expectedValues)) { |
461
|
|
|
|
|
|
|
$valued = 0; |
462
|
|
|
|
|
|
|
foreach my $value (@expectedValues) { |
463
|
|
|
|
|
|
|
if(ref($value) =~ /^$/) { |
464
|
|
|
|
|
|
|
if($value == %{$parameters{SUPPLIED}}->{$expectedKey}) { |
465
|
|
|
|
|
|
|
$valued = 1; |
466
|
|
|
|
|
|
|
last; |
467
|
|
|
|
|
|
|
} |
468
|
|
|
|
|
|
|
} elsif(ref($value) =~ /^HASH$/i) { |
469
|
|
|
|
|
|
|
if(defined(%{%{$parameters{SUPPLIED}}->{$expectedKey}}->{REFERENCE})) { |
470
|
|
|
|
|
|
|
last if(%{%{$parameters{SUPPLIED}}->{$expectedKey}}->{REFERENCE} ne ref(%{$parameters{SUPPLIED}}->{$expectedKey})); |
471
|
|
|
|
|
|
|
} |
472
|
|
|
|
|
|
|
if(defined(%{%{$parameters{SUPPLIED}}->{$expectedKey}}->{REFERENCE})) { |
473
|
|
|
|
|
|
|
} else { |
474
|
|
|
|
|
|
|
$valued = 1; |
475
|
|
|
|
|
|
|
last; |
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
} |
479
|
|
|
|
|
|
|
} else { |
480
|
|
|
|
|
|
|
$valued = 1; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
if(0 == $valued) { |
483
|
|
|
|
|
|
|
$match = 0; |
484
|
|
|
|
|
|
|
last; |
485
|
|
|
|
|
|
|
} |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
if($match) { |
489
|
|
|
|
|
|
|
$valid = $index; |
490
|
|
|
|
|
|
|
last; |
491
|
|
|
|
|
|
|
} |
492
|
|
|
|
|
|
|
} |
493
|
|
|
|
|
|
|
return $valid; |
494
|
|
|
|
|
|
|
} |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
################################################################################ |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=end comment |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
=cut |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
=head2 hasSubroutine |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
my $SUBROUTINE_ARRAY = $OBJECT->hasSubroutine(); |
506
|
|
|
|
|
|
|
if(defined($SUBROUTINE_ARRAY)); |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
if(1 == $OBJECT->hasSubroutine( |
509
|
|
|
|
|
|
|
'someSubroutine', |
510
|
|
|
|
|
|
|
'anotherSubroutine', |
511
|
|
|
|
|
|
|
'etc' |
512
|
|
|
|
|
|
|
)); |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=over 4 |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item self I<(Blessed Hash, Required)> |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
An object of this namespace. |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item name I<(Array B String, Optional)> |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
A namespace or an array of namespaces. |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=back |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
Either returns an array of all the subroutines in the loaded module or whether |
527
|
|
|
|
|
|
|
the loaded module has all of the specified subroutines with a B<1> I<(one)> for |
528
|
|
|
|
|
|
|
yes and B<0> I<(zero)> for no. |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=cut |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
sub hasSubroutine { |
534
|
0
|
0
|
|
0
|
1
|
|
return if(0 == scalar(@_)); |
535
|
0
|
|
|
|
|
|
my $self = shift(@_); |
536
|
0
|
0
|
|
|
|
|
return if(ref($self) =~ /^(|ARRAY|CODE|FORMAT|GLOB|HASH|IO|LVALUE|REF|Regexp|SCALAR|VSTRING)$/i); |
537
|
1
|
|
|
1
|
|
80687
|
no strict 'refs'; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
242
|
|
538
|
0
|
|
|
|
|
|
my %subroutines = map { $_ => 1 } grep { exists &{"$self\::$_"} } keys %{"$self\::"}; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
539
|
0
|
0
|
|
|
|
|
if(0 == scalar(@_)) { |
540
|
0
|
0
|
|
|
|
|
return [( keys(%subroutines) )] if(0 < scalar(keys(%subroutines))); |
541
|
0
|
|
|
|
|
|
return; |
542
|
|
|
|
|
|
|
} |
543
|
0
|
|
|
|
|
|
while(0 < scalar(@_)) { |
544
|
0
|
|
|
|
|
|
my $name = shift(@_); |
545
|
0
|
0
|
|
|
|
|
return 0 if(ref($name) !~ /^$/); |
546
|
0
|
0
|
|
|
|
|
return 0 if(!defined($subroutines{$name})); |
547
|
|
|
|
|
|
|
} |
548
|
0
|
|
|
|
|
|
return 1; |
549
|
|
|
|
|
|
|
} |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
=head1 NOTES |
553
|
|
|
|
|
|
|
|
554
|
|
|
|
|
|
|
This module is designed to make it simple, easy and quite fast to code your |
555
|
|
|
|
|
|
|
design in perl. If for any reason you feel that it doesn't achieve these goals |
556
|
|
|
|
|
|
|
then please let me know. I am here to help. All constructive criticisms are |
557
|
|
|
|
|
|
|
also welcomed. |
558
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
=cut |
560
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
|
562
|
1
|
|
|
1
|
|
148
|
INIT { |
563
|
|
|
|
|
|
|
} |
564
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
|
566
|
|
|
|
|
|
|
=head1 AUTHOR |
567
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
Kevin Treleaven treleaven I net> |
569
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
=cut |
571
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
1; |