line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
############# |
2
|
|
|
|
|
|
|
# Created By: setitesuk@gmail.com |
3
|
|
|
|
|
|
|
# Created On: 2009-11-03 |
4
|
|
|
|
|
|
|
# Last Updated: 2009-11-09 |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
package MooseX::AttributeCloner; |
7
|
1
|
|
|
1
|
|
3401982
|
use Moose::Role; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
9
|
|
8
|
1
|
|
|
1
|
|
4743
|
use Carp qw{carp cluck croak confess}; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
80
|
|
9
|
1
|
|
|
1
|
|
6
|
use English qw{-no_match_vars}; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
9
|
|
10
|
1
|
|
|
1
|
|
1248
|
use Readonly; |
|
1
|
|
|
|
|
2924
|
|
|
1
|
|
|
|
|
43
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
6
|
use JSON; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
8
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
our $VERSION = 0.27; |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
Readonly::Scalar our $ATTRIBUTE_METACLASS_TO_SKIP => q[MooseX::Getopt::Meta::Attribute::NoGetopt]; |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
MooseX::AttributeCloner |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 VERSION |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
0.27 |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
=head1 SYNOPSIS |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
package My::Class; |
29
|
|
|
|
|
|
|
use Moose; |
30
|
|
|
|
|
|
|
with qw{MooseX::AttributeCloner}; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
my $NewClassObject = $self->new_with_cloned_attributes(q{New::Class}, {}); |
33
|
|
|
|
|
|
|
1; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 DESCRIPTION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
The purpose of this Role is to take all the attributes which have values in the current class, |
38
|
|
|
|
|
|
|
and populate them directly into a new class object. The purpose of which is that if you have data |
39
|
|
|
|
|
|
|
inputted on the command line that needs to propagate through to later class objects, you shouldn't |
40
|
|
|
|
|
|
|
need to do the following |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
my $oNewClass = New::Class->new({ |
43
|
|
|
|
|
|
|
attr1 => $self->attr1, |
44
|
|
|
|
|
|
|
attr2 => $self->attr2, |
45
|
|
|
|
|
|
|
... |
46
|
|
|
|
|
|
|
}); |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
Which is going to get, quite frankly, tedious in the extreme. Particularly when you have more 2 class |
49
|
|
|
|
|
|
|
objects in your chain. |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
=head2 new_with_cloned_attributes |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
This takes a package name as the first argument, plus an optional additional $arg_refs hash. It will |
56
|
|
|
|
|
|
|
return a class object of the package populated with any matching attribute data from the current object, |
57
|
|
|
|
|
|
|
plus anything in the $arg_refs hash. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=cut |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub new_with_cloned_attributes { |
62
|
4
|
|
|
4
|
1
|
3847
|
my ($self, $package, $arg_refs) = @_; |
63
|
4
|
|
100
|
|
|
368
|
$arg_refs ||= {}; |
64
|
|
|
|
|
|
|
|
65
|
4
|
100
|
66
|
|
|
25
|
if (!ref$self && ref$package) { |
66
|
1
|
|
|
|
|
2
|
my $temp = $self; |
67
|
1
|
|
|
|
|
2
|
$self = $package; |
68
|
1
|
|
|
|
|
2
|
$package = $temp; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
eval { |
72
|
4
|
|
|
|
|
12
|
my $package_file_name = $package; |
73
|
4
|
|
|
|
|
10
|
$package_file_name =~ s{::}{/}gxms; |
74
|
4
|
50
|
|
|
|
18
|
if ($package_file_name !~ /[.]pm\z/xms) { |
75
|
4
|
|
|
|
|
9
|
$package_file_name .= q{.pm}; |
76
|
|
|
|
|
|
|
} |
77
|
4
|
|
|
|
|
42
|
require $package_file_name; |
78
|
4
|
50
|
|
|
|
8
|
} or do { |
79
|
0
|
|
|
|
|
0
|
confess $EVAL_ERROR; |
80
|
|
|
|
|
|
|
}; |
81
|
4
|
|
|
|
|
21
|
$self->_hash_of_attribute_values($arg_refs); |
82
|
4
|
|
|
|
|
126
|
return $package->new($arg_refs); |
83
|
|
|
|
|
|
|
} |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=head2 attributes_as_command_options |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
returns all the built attributes that are not objects as a string of command_line options |
88
|
|
|
|
|
|
|
only the first level of references will be passed through, multi-dimensional data structures |
89
|
|
|
|
|
|
|
should use the json serialisation option and deserialise it on object construction or script |
90
|
|
|
|
|
|
|
running |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
my $command_line_string = $class->attributes_as_command_options(); |
93
|
|
|
|
|
|
|
--attr1 val1 --attr2 val2 |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
By default, it returns the options with a double dash, space separated, and not quoted (as above). These can be switched by submitting a hash_ref as follows |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
my $command_line_string = $class->attributes_as_command_options({ |
98
|
|
|
|
|
|
|
equal => 1, |
99
|
|
|
|
|
|
|
quotes => 1, |
100
|
|
|
|
|
|
|
single_dash => 1, |
101
|
|
|
|
|
|
|
}); |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
Although, if you are passing a hash_ref, this will always be space separated attr val. |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
You may exclude some values if you wish. To do this, use the example below |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
my $command_line_string = $class->attributes_as_command_options({ |
108
|
|
|
|
|
|
|
excluded_attributes => [ qw( init_arg1 init_arg2 init_arg3 ) ], |
109
|
|
|
|
|
|
|
}); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
Note here you are using the init_arg, rather than any reader/accessor method names to exclude the option, as it is the init_arg which will be used in the command_line string generated |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
Sometimes you may have floating attributes for argv and ARGV (we have discovered this with MooseX::Getopt). As such, these are being treated as 'special', and these will be excluded by default. You can request them to be included as follows. |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my $command_line_string = $class->attributes_as_command_options({ |
116
|
|
|
|
|
|
|
included_argv_attributes => [ qw( argv ARGV ) ], |
117
|
|
|
|
|
|
|
}); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
No additional command_line params can be pushed into this, it only deals with the attributes already set in the current object |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
Note, it is your responsibility to know where you may need any of these to be on or off, unless they have no init_arg (init_arg => undef) |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
From v0.25, any attributes with a metaclass of NoGetopt will not be translated to a command line as they would cause a failure to any new_with_options with MooseX::Getopt. You can override this by passing an additional argument 'include_no_getopt' |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
my $command_line_string = $class->attributes_as_command_options({ |
126
|
|
|
|
|
|
|
included_argv_attributes => [ qw( argv ARGV ) ], |
127
|
|
|
|
|
|
|
include_no_getopt => 1, |
128
|
|
|
|
|
|
|
}); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=cut |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub attributes_as_command_options { |
133
|
11
|
|
|
11
|
1
|
7950
|
my ($self,$arg_refs) = @_; |
134
|
11
|
|
100
|
|
|
47
|
$arg_refs ||= {}; |
135
|
|
|
|
|
|
|
|
136
|
11
|
|
|
|
|
49
|
my $attributes = $self->_hash_of_attribute_values({command_options => 1}); |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# exclude any specified init_args |
139
|
11
|
|
|
|
|
111
|
$self->_exclude_args($attributes, $arg_refs); |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
# remove any objects from the hash |
142
|
7
|
|
|
|
|
26
|
$self->_traverse_hash($attributes); |
143
|
|
|
|
|
|
|
|
144
|
7
|
|
|
|
|
9
|
my @command_line_options; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
# version 0.21 - force this to be in a sorted order, so that results can be consistent should operating systems return keys in a different order |
147
|
7
|
|
|
|
|
12
|
foreach my $key (sort keys %{$attributes}) { |
|
7
|
|
|
|
|
43
|
|
148
|
|
|
|
|
|
|
|
149
|
31
|
100
|
66
|
|
|
124
|
if (! ref $attributes->{$key} |
|
|
|
66
|
|
|
|
|
150
|
|
|
|
|
|
|
&& |
151
|
|
|
|
|
|
|
( (ref( $self->meta()->get_attribute($key) ) ne $ATTRIBUTE_METACLASS_TO_SKIP ) || $arg_refs->{include_no_getopt} ) ) { |
152
|
18
|
|
|
|
|
563
|
my $string = $self->_create_string($key, $attributes->{$key}, $arg_refs); |
153
|
18
|
|
|
|
|
28
|
push @command_line_options, $string; |
154
|
18
|
|
|
|
|
41
|
next; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
13
|
100
|
|
|
|
74
|
if (ref $attributes->{$key} eq q{HASH}) { |
158
|
|
|
|
|
|
|
|
159
|
5
|
|
|
|
|
8
|
foreach my $h_key (sort {$a cmp $b} keys %{$attributes->{$key}}) { |
|
5
|
|
|
|
|
14
|
|
|
5
|
|
|
|
|
28
|
|
160
|
|
|
|
|
|
|
|
161
|
10
|
50
|
33
|
|
|
81
|
if (defined $attributes->{$key}->{$h_key} && ! ref $attributes->{$key}->{$h_key}) { # don't pass through empty strings or references |
162
|
10
|
|
|
|
|
39
|
my $string = $self->_create_string($key, qq{$h_key=$attributes->{$key}->{$h_key}}, $arg_refs, 1); |
163
|
10
|
|
|
|
|
24
|
push @command_line_options, $string; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} |
169
|
|
|
|
|
|
|
|
170
|
13
|
100
|
|
|
|
44
|
if (ref $attributes->{$key} eq q{ARRAY}) { |
171
|
|
|
|
|
|
|
|
172
|
7
|
|
|
|
|
9
|
foreach my $value (@{$attributes->{$key}}) { |
|
7
|
|
|
|
|
19
|
|
173
|
|
|
|
|
|
|
|
174
|
30
|
100
|
100
|
|
|
126
|
if (defined $value && ! ref $value) { # don't pass through empty strings or references |
175
|
18
|
|
|
|
|
43
|
my $string = $self->_create_string($key, $value, $arg_refs); |
176
|
18
|
|
|
|
|
65
|
push @command_line_options, $string; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
} |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
} |
184
|
|
|
|
|
|
|
|
185
|
7
|
|
|
|
|
13
|
my $clo_string; |
186
|
7
|
100
|
|
|
|
17
|
if ($arg_refs->{single_dash}) { |
187
|
2
|
|
|
|
|
8
|
$clo_string = join q{ -}, @command_line_options; |
188
|
2
|
|
|
|
|
7
|
$clo_string = q{-} . $clo_string; |
189
|
|
|
|
|
|
|
} else { |
190
|
5
|
|
|
|
|
16
|
$clo_string = join q{ --}, @command_line_options; |
191
|
5
|
|
|
|
|
12
|
$clo_string = q{--} . $clo_string; |
192
|
|
|
|
|
|
|
} |
193
|
7
|
|
|
|
|
59
|
return $clo_string; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
|
|
|
|
|
|
=head2 attributes_as_json |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
returns all the built attributes that are not objects as a JSON string |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
my $sAttributesAsJSON = $class->attributes_as_json(); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
=head2 attributes_as_escaped_json |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
as attributes_as_json, except it is an escaped JSON string, so that this could be used on a command line |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
my $sAttributesAsEscapedJSON = $class->attributes_as_escaped_json(); |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
This uses JSON to generate the string, removing any objects before stringifying, and then parses it through a regex to generate a string with escaped characters |
209
|
|
|
|
|
|
|
Note, because objects are removed, arrays will remain the correct length, but have null in them |
210
|
|
|
|
|
|
|
=cut |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub attributes_as_escaped_json { |
213
|
1
|
|
|
1
|
1
|
1482
|
my ($self) = @_; |
214
|
1
|
|
|
|
|
5
|
my $json = $self->attributes_as_json(); |
215
|
1
|
|
|
|
|
90
|
$json =~ s{([^\w\d-])}{\\$1}gmxs; |
216
|
1
|
|
|
|
|
6
|
return $json; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
sub attributes_as_json { |
220
|
2
|
|
|
2
|
1
|
3734
|
my ($self) = @_; |
221
|
|
|
|
|
|
|
|
222
|
2
|
|
|
|
|
10
|
my $attributes = $self->_hash_of_attribute_values(); |
223
|
|
|
|
|
|
|
# remove any objects from the hash |
224
|
2
|
|
|
|
|
9
|
$self->_traverse_hash($attributes); |
225
|
2
|
|
|
|
|
11
|
my $json = to_json($attributes); |
226
|
2
|
|
|
|
|
84
|
return $json; |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=head2 attributes_as_hashref |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Returns a hashref of the attributes this object has built, |
232
|
|
|
|
|
|
|
optionally excluding any specified attributes. |
233
|
|
|
|
|
|
|
Includes objects which may have been built. |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
my $hAttributesAsHashref = $class->attributes_as_hashref({ |
236
|
|
|
|
|
|
|
excluded_attributes => [ qw( init_arg1 init_arg2 init_arg3 ) ], |
237
|
|
|
|
|
|
|
}); |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
Note here you are using the init_arg, rather than any reader/accessor method names to exclude the option |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=cut |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub attributes_as_hashref { |
244
|
1
|
|
|
1
|
1
|
2
|
my ( $self, $arg_refs ) = @_; |
245
|
1
|
|
50
|
|
|
4
|
$arg_refs ||= {}; |
246
|
1
|
|
|
|
|
4
|
my $attributes = $self->_hash_of_attribute_values(); |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
# exclude any specified init_args |
249
|
1
|
|
|
|
|
3
|
$self->_exclude_args($attributes, $arg_refs); |
250
|
1
|
|
|
|
|
3
|
return $attributes; |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
############### |
254
|
|
|
|
|
|
|
# private methods |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
# a hash_ref of attribute values from $self, where built |
258
|
|
|
|
|
|
|
# either acts on a provided hash_ref, or will return a new one |
259
|
|
|
|
|
|
|
sub _hash_of_attribute_values { |
260
|
18
|
|
|
18
|
|
32
|
my ($self, $arg_refs) = @_; |
261
|
18
|
|
100
|
|
|
52
|
$arg_refs ||= {}; |
262
|
|
|
|
|
|
|
|
263
|
18
|
|
|
|
|
31
|
my $command_options = $arg_refs->{command_options}; |
264
|
18
|
|
|
|
|
29
|
delete$arg_refs->{command_options}; |
265
|
|
|
|
|
|
|
|
266
|
18
|
|
|
|
|
78
|
my @attributes = $self->meta->get_all_attributes(); |
267
|
18
|
|
|
|
|
1177
|
foreach my $attr (@attributes) { |
268
|
276
|
|
66
|
|
|
9777
|
my $reader = $attr->reader() || $attr->accessor(); |
269
|
276
|
|
|
|
|
833
|
my $init_arg = $attr->init_arg(); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
# if there is no reader/accessor method, then we can't read the attribute value, so skip |
272
|
276
|
50
|
|
|
|
539
|
next if (!$reader); |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# if the reader/accessor are private, then we don't want to pass it around |
275
|
276
|
50
|
|
|
|
557
|
next if ($reader =~ /\A_/xms); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# if lazy_build, then will only propagate data if it is built, saving any expensive build routines. |
278
|
|
|
|
|
|
|
# obviously, this has the effect that you may need to do it twice, or force a build before the cloning of data |
279
|
|
|
|
|
|
|
# NOTE: this doesn't account for those which are lazy, and have a builder, but no predicate (generated by lazy_build flag only) |
280
|
276
|
100
|
|
|
|
660
|
if ($attr->{predicate}) { |
281
|
18
|
|
|
|
|
28
|
my $pred = $attr->{predicate}; |
282
|
18
|
100
|
|
|
|
556
|
next if !$self->$pred(); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
274
|
100
|
33
|
|
|
9286
|
if ($init_arg && !exists$arg_refs->{$init_arg} && defined $self->$reader()) { |
|
|
|
66
|
|
|
|
|
286
|
100
|
50
|
100
|
|
|
3947
|
next if ( $attr->type_constraint() eq q{Bool} && $command_options && ! $self->$reader ); |
|
|
|
66
|
|
|
|
|
287
|
100
|
100
|
100
|
|
|
10385
|
$arg_refs->{$init_arg} = $attr->type_constraint() eq q{Bool} && $command_options ? q{} : $self->$reader(); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
} |
290
|
|
|
|
|
|
|
|
291
|
18
|
|
|
|
|
337
|
return $arg_refs; |
292
|
|
|
|
|
|
|
} |
293
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
# remove any objects from a hash |
295
|
|
|
|
|
|
|
sub _traverse_hash { |
296
|
24
|
|
|
24
|
|
36
|
my ($self, $hash) = @_; |
297
|
24
|
|
|
|
|
27
|
my @keys_to_delete; |
298
|
24
|
|
|
|
|
27
|
foreach my $key (keys %{$hash}) { |
|
24
|
|
|
|
|
72
|
|
299
|
78
|
100
|
|
|
|
193
|
next if (!ref $hash->{$key}); |
300
|
25
|
100
|
|
|
|
66
|
if (ref$hash->{$key} eq q{HASH}) { |
301
|
7
|
|
|
|
|
27
|
$self->_traverse_hash($hash->{$key}); |
302
|
7
|
|
|
|
|
10
|
next; |
303
|
|
|
|
|
|
|
} |
304
|
18
|
100
|
|
|
|
51
|
if (ref$hash->{$key} eq q{ARRAY}) { |
305
|
9
|
|
|
|
|
30
|
$hash->{$key} = $self->_traverse_array($hash->{$key}); |
306
|
9
|
|
|
|
|
16
|
next; |
307
|
|
|
|
|
|
|
} |
308
|
9
|
|
|
|
|
51
|
push @keys_to_delete, $key; |
309
|
|
|
|
|
|
|
} |
310
|
24
|
|
|
|
|
54
|
foreach my $key (@keys_to_delete) { |
311
|
9
|
|
|
|
|
22
|
delete $hash->{$key}; |
312
|
|
|
|
|
|
|
} |
313
|
24
|
|
|
|
|
41
|
return $hash; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
# remove any objects from an array |
317
|
|
|
|
|
|
|
sub _traverse_array { |
318
|
9
|
|
|
9
|
|
15
|
my ($self, $array) = @_; |
319
|
9
|
|
|
|
|
15
|
my @wanted_items; |
320
|
9
|
|
|
|
|
14
|
foreach my $item (@{$array}) { |
|
9
|
|
|
|
|
20
|
|
321
|
40
|
100
|
|
|
|
81
|
if (!ref $item) { |
322
|
24
|
|
|
|
|
33
|
push @wanted_items, $item; |
323
|
24
|
|
|
|
|
30
|
next; |
324
|
|
|
|
|
|
|
} |
325
|
16
|
100
|
|
|
|
37
|
if (ref$item eq q{HASH}) { |
326
|
8
|
|
|
|
|
20
|
$self->_traverse_hash($item); |
327
|
8
|
|
|
|
|
13
|
push @wanted_items, $item; |
328
|
8
|
|
|
|
|
9
|
next; |
329
|
|
|
|
|
|
|
} |
330
|
8
|
50
|
|
|
|
19
|
if (ref$item eq q{ARRAY}) { |
331
|
0
|
|
|
|
|
0
|
$item = $self->_traverse_array($item); |
332
|
0
|
|
|
|
|
0
|
push @wanted_items, $item; |
333
|
0
|
|
|
|
|
0
|
next; |
334
|
|
|
|
|
|
|
} |
335
|
8
|
|
|
|
|
27
|
push @wanted_items, undef; |
336
|
|
|
|
|
|
|
} |
337
|
9
|
|
|
|
|
25
|
return \@wanted_items; |
338
|
|
|
|
|
|
|
} |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
############ |
341
|
|
|
|
|
|
|
# remove any unwanted options by the init_arg they would have |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
sub _exclude_args { |
344
|
12
|
|
|
12
|
|
22
|
my ($self, $attributes, $arg_refs) = @_; |
345
|
12
|
|
100
|
|
|
68
|
my $excluded_attributes = $arg_refs->{excluded_attributes} || []; |
346
|
12
|
|
|
|
|
21
|
delete $arg_refs->{excluded_attributes}; |
347
|
12
|
|
100
|
|
|
53
|
my $included_argv_attributes = $arg_refs->{included_argv_attributes} || []; |
348
|
12
|
|
|
|
|
20
|
delete $arg_refs->{included_argv_attributes}; |
349
|
12
|
0
|
33
|
|
|
32
|
if (!$excluded_attributes && !$included_argv_attributes) { |
350
|
0
|
|
|
|
|
0
|
return 1; |
351
|
|
|
|
|
|
|
} |
352
|
|
|
|
|
|
|
|
353
|
12
|
100
|
100
|
|
|
74
|
if ( ! ref$excluded_attributes || ref$excluded_attributes ne q{ARRAY} ) { |
354
|
2
|
|
|
|
|
39
|
croak qq{Your excluded_attributes are not in an arrayref - $excluded_attributes}; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
10
|
100
|
100
|
|
|
64
|
if ( ! ref$included_argv_attributes || ref$included_argv_attributes ne q{ARRAY} ) { |
358
|
2
|
|
|
|
|
24
|
croak qq{Your included_argv_attributes are not in an arrayref - $included_argv_attributes}; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
8
|
|
|
|
|
15
|
foreach my $exclusion (@{$excluded_attributes}) { |
|
8
|
|
|
|
|
40
|
|
362
|
3
|
|
|
|
|
6
|
delete $attributes->{$exclusion}; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
8
|
|
|
|
|
18
|
my $wanted_argv = {}; |
366
|
8
|
|
|
|
|
11
|
foreach my $inclusion (@{$included_argv_attributes}) { |
|
8
|
|
|
|
|
17
|
|
367
|
2
|
|
|
|
|
7
|
$wanted_argv->{$inclusion}++; |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
|
370
|
8
|
|
|
|
|
15
|
foreach my $argv ( qw{ argv ARGV }) { |
371
|
16
|
100
|
|
|
|
44
|
if (!$wanted_argv->{$argv}) { |
372
|
14
|
|
|
|
|
28
|
delete $attributes->{$argv}; |
373
|
|
|
|
|
|
|
} |
374
|
|
|
|
|
|
|
} |
375
|
|
|
|
|
|
|
|
376
|
8
|
|
|
|
|
24
|
return 1; |
377
|
|
|
|
|
|
|
} |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
# create a command line string |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
sub _create_string { |
382
|
46
|
|
|
46
|
|
66
|
my ($self, $attr, $value, $arg_refs, $hash) = @_; |
383
|
46
|
|
|
|
|
54
|
my $string = $attr; |
384
|
|
|
|
|
|
|
|
385
|
46
|
100
|
100
|
|
|
330
|
if ($value ne q{} && !$hash && $arg_refs->{equal}) { |
|
|
|
100
|
|
|
|
|
386
|
10
|
|
|
|
|
19
|
$string .= q{=}; |
387
|
|
|
|
|
|
|
} else { |
388
|
36
|
|
|
|
|
59
|
$string .= q{ }; # default attr value separator |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
46
|
100
|
100
|
|
|
172
|
if ($value ne q{} && $arg_refs->{quotes}) { |
392
|
14
|
|
|
|
|
24
|
$string .= qq{"$value"}; |
393
|
|
|
|
|
|
|
} else { |
394
|
32
|
|
|
|
|
39
|
$string .= qq{$value}; # default no quote of value |
395
|
|
|
|
|
|
|
} |
396
|
46
|
|
|
|
|
94
|
return $string; |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
1; |
400
|
|
|
|
|
|
|
__END__ |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head1 DIAGNOSTICS |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=head1 CONFIGURATION AND ENVIRONMENT |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=head1 DEPENDENCIES |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=over |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
=item Moose::Role |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=item Carp |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
=item English -no_match_vars |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=item Readonly |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=item JSON |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=back |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=head1 INCOMPATIBILITIES |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head1 BUGS AND LIMITATIONS |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
This is more than likely to have bugs in it. Please contact me with any you find (or submit to RT) |
427
|
|
|
|
|
|
|
and any patches. |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=head1 AUTHOR |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
setitesuk |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
Copyright (C) 2011 Andy Brown (setitesuk@gmail.com) |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify |
438
|
|
|
|
|
|
|
it under the terms of the GNU General Public License as published by |
439
|
|
|
|
|
|
|
the Free Software Foundation, either version 3 of the License, or |
440
|
|
|
|
|
|
|
(at your option) any later version. |
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
443
|
|
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
444
|
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
445
|
|
|
|
|
|
|
GNU General Public License for more details. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License |
448
|
|
|
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |