File Coverage

blib/lib/Data/Verifier.pm
Criterion Covered Total %
statement 171 175 97.7
branch 69 82 84.1
condition 32 39 82.0
subroutine 12 12 100.0
pod 2 2 100.0
total 286 310 92.2


line stmt bran cond sub pod time code
1             package Data::Verifier;
2             $Data::Verifier::VERSION = '0.61';
3 17     17   550244 use Moose;
  17         4334501  
  17         88  
4              
5             # ABSTRACT: Profile based data verification with Moose type constraints.
6              
7 17     17   83722 use Data::Verifier::Field;
  17         42  
  17         617  
8 17     17   8290 use Data::Verifier::Filters;
  17         25  
  17         434  
9 17     17   5378 use Data::Verifier::Results;
  17         43  
  17         539  
10 17     17   127 use Moose::Util::TypeConstraints;
  17         21  
  17         128  
11 17     17   22660 use Scalar::Util qw(blessed);
  17         23  
  17         820  
12 17     17   83 use Try::Tiny;
  17         19  
  17         19798  
13              
14              
15              
16             has 'derived' => (
17             is => 'ro',
18             isa => 'HashRef[HashRef]',
19             predicate => 'has_derived'
20             );
21              
22              
23             has 'filters' => (
24             is => 'ro',
25             isa => 'ArrayRef[Str|CodeRef]',
26             default => sub { [] }
27             );
28              
29              
30              
31             has 'profile' => (
32             is => 'ro',
33             isa => 'HashRef[HashRef]',
34             required => 1
35             );
36              
37              
38             sub coercion {
39 2     2 1 20 my %params = @_;
40             Moose::Meta::TypeCoercion->new(
41             type_coercion_map => [
42 2         16 $params{'from'} => $params{'via'}
43             ]
44             );
45             }
46              
47              
48             sub verify {
49 112     112 1 1596 my ($self, $params, $members) = @_;
50              
51 112         2819 my $results = Data::Verifier::Results->new;
52 112         2234 my $profile = $self->profile;
53              
54 112         154 my $blessed_params = blessed($params);
55              
56 112         153 my @post_checks = ();
57 112         92 foreach my $key (keys(%{ $profile })) {
  112         220  
58 155         130 my $skip_string_checks = 0;
59              
60             # Get the profile part that is pertinent to this field
61 155         149 my $fprof = $profile->{$key};
62              
63             # Deal with the fact that what we're given may be an object.
64 155         108 my $val = do {
65 155 100       197 if($blessed_params) {
66 4 100       48 $params->can($key) ? $params->$key() : undef;
67             } else {
68 151         175 $params->{$key};
69             }
70             };
71              
72             # Creat the "field" that we'll put into the result.
73 155         3492 my $field = Data::Verifier::Field->new;
74              
75             # Save the original value.
76 155 100       491 if(ref($val) eq 'ARRAY') {
77 17         17 my @values = @{ $val }; # Make a copy of the array
  17         36  
78 17         418 $field->original_value(\@values);
79             } else {
80 138         3287 $field->original_value($val);
81             }
82              
83             # Early type check to catch parameterized ArrayRefs.
84 155 100       278 if($fprof->{type}) {
85 103         263 my $cons = Moose::Util::TypeConstraints::find_or_parse_type_constraint($fprof->{type});
86              
87 103 50       24148 die "Unknown type constraint '$fprof->{type}'" unless defined($cons);
88              
89             # If this type is a paramterized arrayref, then we'll handle each
90             # param as if it was an independet value and run it through the
91             # whole profile.
92 103 100 66     224 if($cons->is_a_type_of('ArrayRef') && $cons->can('type_parameter')) {
93              
94             # Get the type parameter for this arrayref
95 18         2670 my $tc = $cons->type_parameter;
96             # Copy the profile.
97 18         83 my %prof_copy = %{ $fprof };
  18         80  
98 18         382 $prof_copy{type} = $tc->name;
99 18         431 my $dv = Data::Verifier->new(
100             # Use the global filters
101             filters => $self->filters,
102             # And JUST this field
103             profile => { $key => \%prof_copy }
104             );
105              
106             # Make sure we are dealing with an array
107 18         22 my @possibles;
108 18 100       32 if(ref($val) eq 'ARRAY') {
109 17         14 @possibles = @{ $val };
  17         32  
110             } else {
111 1         3 @possibles = ( $val );
112             }
113              
114             # So we can keep up with passed values.
115 18         17 my @passed;
116             my @pass_post_filter;
117             # Verify each one
118 18         25 foreach my $poss (@possibles) {
119 50         159 my $res = $dv->verify({ $key => $poss }, 1);
120 50 100       134 if($res->success) {
121             # We need to keep up with passed values as well as
122             # post filter values, copying them out of the result
123             # for use in our field.
124 44         84 push(@passed, $res->get_value($key));
125 44         95 push(@pass_post_filter, $res->get_post_filter_value($key));
126             } else {
127             # Mark the whole field as failed. We'll use this
128             # later.
129 6         155 $field->valid(0);
130             }
131             }
132              
133             # Set the value and post_filter_value for the field, then
134             # set the field in the result. We're done, since we sorta
135             # recursed to check all the params for this field.
136 18         24 $val = \@passed;
137 18         385 $field->value(\@passed);
138 18         402 $field->post_filter_value(\@pass_post_filter);
139 18         493 $results->set_field($key, $field);
140              
141             # Skip all the "string" checks, since we've already done all the
142             # real work.
143 18         402 $skip_string_checks = 1;
144             }
145 103 100       35007 next unless $field->valid; # stop processing if invalid
146             }
147              
148 151 100       244 unless($skip_string_checks) {
149             # Pass through global filters
150 137 50       2780 if($self->filters ) {
151 137         2568 $val = $self->_filter_value($self->filters, $val);
152             }
153              
154             # And now per-field ones
155 136 100       233 if($fprof->{filters} ) {
156 11         15 $val = $self->_filter_value($fprof->{filters}, $val);
157             }
158              
159             # Empty strings are undefined
160 136 50 66     454 if(defined($val) && $val eq '') {
161 0         0 $val = undef;
162             }
163              
164 136 50       184 if(ref($val) eq 'ARRAY' ) {
165 0         0 my @values = @{ $val };
  0         0  
166 0         0 $field->post_filter_value(\@values);
167             } else {
168 136         3260 $field->post_filter_value($val);
169             }
170              
171 136 100 100     368 if($fprof->{required} && !defined($val)) {
172             # Set required fields to undef, as they are missing
173 8         226 $results->set_field($key, undef);
174             } else {
175 128         3697 $results->set_field($key, $field);
176             }
177              
178             # No sense in continuing if the value isn't defined.
179 136 100       416 next unless defined($val);
180              
181             # Check min length
182 126 100 100     252 if($fprof->{min_length} && length($val) < $fprof->{min_length}) {
183 2         45 $field->reason('min_length');
184 2         42 $field->valid(0);
185 2         4 next; # stop processing!
186             }
187              
188             # Check max length
189 124 100 100     243 if($fprof->{max_length} && length($val) > $fprof->{max_length}) {
190 2         45 $field->reason('max_length');
191 2         44 $field->valid(0);
192 2         3 next; # stop processing!
193             }
194             }
195              
196             # Validate it
197 136 100       204 if($fprof->{type}) {
198 93         208 my $cons = Moose::Util::TypeConstraints::find_or_parse_type_constraint($fprof->{type});
199              
200 93 50       6587 die "Unknown type constraint '$fprof->{type}'" unless defined($cons);
201              
202             # Look for a global coercion
203 93 100       228 if($fprof->{coerce}) {
    100          
204 2         6 $val = $cons->coerce($val);
205             }
206             # Try a one-off coercion.
207             elsif(my $coercion = $fprof->{coercion}) {
208 2         7 $val = $coercion->coerce($val);
209             }
210              
211 93 100       1003 unless($cons->check($val)) {
212 8         703 $field->reason('type_constraint');
213 8         172 $field->valid(0);
214 8         208 $field->clear_value;
215 8         18 next; # stop processing!
216             }
217             }
218              
219             # check for dependents
220 128         4665 my $dependent = $fprof->{dependent};
221 128         94 my $dep_results;
222 128 100 100     253 if($dependent and !$members) {
223             # Create a new verifier for use with the dependents
224 8         169 my $dep_verifier = Data::Verifier->new(
225             filters => $self->filters,
226             profile => $dependent
227             );
228 8         29 $dep_results = $dep_verifier->verify($params);
229              
230             # Merge the dependent's results with the parent one
231 8         17 $results->merge($dep_results);
232              
233             # If the dependent isn't valid, then this field isn't either
234 8 100       17 unless($dep_results->success) {
235 1         24 $field->reason('dependent');
236 1         22 $field->valid(0);
237 1         24 $field->clear_value;
238 1         20 next; # stop processing!
239             }
240             }
241              
242             # Add this key the post check so we know to run through them
243 127 50 100     392 if(!$members && defined($fprof->{post_check}) && $fprof->{post_check}) {
      66        
244 12         18 push(@post_checks, $key);
245             }
246             # Add this key to the post check if we're on "member" mode and there
247             # is a member_post_check specified
248 127 50 100     353 if($members && defined($fprof->{member_post_check}) && $fprof->{member_post_check}) {
      66        
249 10         12 push(@post_checks, $key);
250             }
251              
252             # Set the value
253 127         2855 $field->value($val);
254 127         2662 $field->valid(1);
255             }
256              
257             # If we have any post checks, do them.
258 111 100       211 if(scalar(@post_checks)) {
259 20         25 foreach my $key (@post_checks) {
260 22         46 my $fprof = $profile->{$key};
261 22         631 my $field = $results->get_field($key);
262              
263             # Execute the post_check...
264              
265             # If we are in member mode, use the member post check, else use
266             # plain ol' post check.
267 22 100       32 my $pc = $members ? $fprof->{member_post_check} : $fprof->{post_check};
268 22 50 33     77 if(defined($pc) && $pc) {
269             try {
270 22 100   22   553 unless($results->$pc()) {
271             # If that returned false, then this field is invalid!
272 7         172 $field->clear_value;
273 7 50       170 $field->reason('post_check') unless $field->has_reason;
274 7         148 $field->valid(0);
275             }
276             } catch {
277 1     1   36 $field->reason($_);
278 1         25 $field->clear_value;
279 1         21 $field->valid(0);
280             }
281 22         129 }
282             }
283             }
284              
285 111 100       2905 if($self->has_derived) {
286 3         4 foreach my $key (keys(%{ $self->derived })) {
  3         58  
287 3         56 my $prof = $self->derived->{$key};
288 3         3 my $der = $prof->{deriver};
289 3 50       5 die "Derived fields must have a deriver!" unless defined($der);
290 3         10 my $rv = $results->$der();
291              
292 3         6 my $req = $prof->{required};
293              
294 3         62 my $field = Data::Verifier::Field->new;
295             # If the field is required and we got back undef then this
296             # is a bad value!
297 3 100 66     14 if(defined($req) && $req && !defined($rv)) {
      100        
298 1         23 $field->valid(0);
299              
300 1         1 my $dfields = $prof->{fields};
301 1         1 foreach my $df (@{ $dfields }) {
  1         2  
302 2         56 my $f = $results->get_field($df);
303 2 50       4 die "Unknown field '$df' in derived field '$key'!" unless defined $f;
304 2         43 $f->valid(0);
305 2         67 $f->value(undef);
306 2         42 $f->reason('derived');
307             }
308             } else {
309             # It's valid, set it to true and put the return value
310             # in.
311 2         45 $field->valid(1);
312 2         43 $field->value($rv);
313 2         42 $field->reason('derived');
314             }
315 3         81 $results->set_field($key, $field);
316             }
317             }
318              
319 111         226 return $results;
320             }
321              
322             sub _filter_value {
323 148     148   154 my ($self, $filters, $values) = @_;
324              
325 148         124 my $created_ref = 0;
326 148 100       255 if(ref($filters) ne 'ARRAY') {
327 4         7 $filters = [ $filters ];
328             }
329             # If we already have an array, just let it be. Otherwise transform the
330             # value into an array. ($values may also be a HashRef[Str] here)
331 148 50       231 unless ( ref $values eq 'ARRAY' ) {
332 148         108 $created_ref = 1;
333 148         201 $values = [ $values ];
334             }
335              
336 148         115 foreach my $f (@{ $filters }) {
  148         231  
337              
338 26         25 foreach my $value (@{ $values }) {
  26         30  
339 26 100       34 if(ref($f)) {
340 7         12 $value = $value->$f($value);
341             } else {
342 19 100       120 die "Unknown filter: $f" unless Data::Verifier::Filters->can($f);
343 18         46 $value = Data::Verifier::Filters->$f($value);
344             }
345             }
346             }
347              
348             # Return an arrayref if we have multiple values or a scalar if we have one
349 147 50       361 return $created_ref ? $values->[0] : $values;
350             }
351              
352             __PACKAGE__->meta->make_immutable;
353              
354             1;
355              
356             __END__
357              
358             =pod
359              
360             =head1 NAME
361              
362             Data::Verifier - Profile based data verification with Moose type constraints.
363              
364             =head1 VERSION
365              
366             version 0.61
367              
368             =head1 DESCRIPTION
369              
370             Data::Verifier allows you verify data (such as web forms, which was the
371             original idea) by leveraging the power of Moose's type constraint system.
372              
373             =head1 MOTIVATION
374              
375             Data::Verifier firstly intends to leverage Moose's type constraint system,
376             which is significantly more powerful than anything I could create for the
377             purposes of this module. Secondly it aims to keep a fairly simple interface
378             by leveraging the aforementioned type system to keep options to a minimum.
379              
380             =head1 NOTES
381              
382             =head2 Multiple Values
383              
384             It should be noted that if you choose to make a param a C<Str> then validation
385             will fail if multiple values are provided. To allow multiple values you
386             must use an C<ArrayRef[Str]>.
387              
388             =head2 ArrayRef based types (more on Multiple Values)
389              
390             If you use an ArrayRef-based parameterized type (e.g. ArrayRef[Str]) then
391             Data::Verifier has the following behavior:
392              
393             Each parameter supplied for the field is checked. If all the members pass
394             then the field is considered valid. If any of the members fail, then the
395             entire field is invalid. If any of the members pass then those members will
396             be included in the C<values> attribute. An example:
397              
398             use Moose::Util::TypeConstraints;
399             use Data::Verifier;
400              
401             subtype 'Over10'
402             => as 'Num'
403             => where { $_ > 10 };
404              
405             my $verifier = Data::Verifier->new(
406             profile => {
407             foos => {
408             type => 'ArrayRef[NumberOver10]',
409             }
410             }
411             );
412              
413             my $res = $verifier->verify(foos => [ 1, 2, 30, 40 ]);
414             $res->success; # This is false, as 1 and 2 did not pass
415             $res->get_value('foos'); # [ 30, 40 ] because 30 and 40 passed!
416             $res->original_value('foos); # [ 1, 2, 30, 40 ] because it's all of them!
417              
418             It should also be noted that C<post_check>s that are specified in the profile
419             do B<not> get applied to the individual members, only to the entire, completed
420             field that they are constituents of.
421              
422             B<Note>: Filters and such DO get applied to individual fields, so something
423             like:
424              
425             my $verifier = Data::Verifier->new(
426             filters => qw(trim),
427             profile => {
428             foos => {
429             type => 'ArrayRef[Str]',
430             filters => 'collapse'
431             }
432             }
433             );
434              
435             In the above example, both C<trim> and C<collapse> B<bill> be applied to each
436             member of foos.
437              
438             =head2 Stops on First Failure
439              
440             Data::Verifier stops checking a field (not all, just the failed one) if it
441             fails any of it's constraints. Consult the Execution Order below to ascertain
442             the order. For example, if a field exceeds it's max length then it will not
443             be checked against it's type constraint.
444              
445             =head2 Serialization
446              
447             Data::Verifier uses L<MooseX::Storage> to allow serialization of
448             L<Data::Verifier::Results> objects. You can use this to store results for
449             validation across redirects. Note, however, that the C<value>
450             attribute is B<not> serialized. Since you can coerce a value into anything
451             it is not reasonable to expect to be able to serialize it. Have a look at
452             the C<original_value> or C<post_filter_value> in L<Data::Verifier::Results>
453             if you want to know more.
454              
455             =head2 Verifying Objects
456              
457             Data::Verifier can verify data encapsulated in objects too. Everything works
458             the way that it does for hash references. Each key in the profile is used as
459             the name of a method to call on the object. In order to maintain consistency
460             with the hash reference case, missing methods pass an 'undef' value into the
461             verification process.
462              
463             =head2 Execution Order
464              
465             It may be important to understand the order in which the various steps of
466             verification are performed:
467              
468             =over 4
469              
470             =item Global Filters
471              
472             Any global filters in the profile are executed.
473              
474             =item Per-Field Filters
475              
476             Any per-field filters are executed.
477              
478             =item Empty String Check
479              
480             If the value of the field is an empty string then it is changed to an undef.
481              
482             =item Required Check
483              
484             The parameter must now be defined if it is set as required.
485              
486             =item Length Check
487              
488             Minimum then maximum length is checked.
489              
490             =item Type Check (w/Coercion)
491              
492             At this point the type will be checked after an optional coercion.
493              
494             =item Dependency Checks
495              
496             If this field has dependents then those will now be processed.
497              
498             =item Post Check
499              
500             If the field has a post check it will now be executed.
501              
502             =item Derived Fields
503              
504             Finally any derived fields are run.
505              
506             =back
507              
508             =encoding utf8
509             =head1 SYNOPSIS
510              
511             use Data::Verifier;
512              
513             my $dv = Data::Verifier->new(
514             filters => [ qw(trim) ],
515             profile => {
516             name => {
517             required => 1,
518             type => 'Str',
519             filters => [ qw(collapse) ]
520             },
521             age => {
522             type => 'Int'
523             },
524             sign => {
525             required => 1,
526             type => 'Str'
527             }
528             }
529             );
530              
531             # Pass in a hash of data
532             my $results = $dv->verify({
533             name => 'Cory', age => 'foobar'
534             });
535              
536             $results->success; # no
537              
538             $results->is_invalid('name'); # no
539             $results->is_invalid('age'); # yes
540              
541             $results->is_missing('name'); # no
542             $results->is_missing('sign'); # yes
543              
544             $results->get_original_value('name'); # Unchanged, original value
545             $results->get_value('name'); # Filtered, valid value
546             $results->get_value('age'); # undefined, as it's invalid
547              
548             =head1 ATTRIBUTES
549              
550             =head2 derived
551              
552             An optional hashref of fields that will be derived from inspecting one or more
553             fields in the profile.
554              
555             The keys for C<derived> are as follows:
556              
557             =over 4
558              
559             =item B<required>
560              
561             Marks this derived field as required. If the C<deriver> returns undef then
562             when this is true then the field, any source C<fields> and (in turn) the entire
563             profile will be invalid.
564              
565             =item B<fields>
566              
567             An optional arrayref that contains the names of any "source" fields that
568             should be considered invalid if this field is determiend to be invalid.
569              
570             =item B<deriver>
571              
572             A subref that is passed a copy of the final results for the profile. The
573             return value of this subref will be used as the value for the field. A return
574             value of undef will cause the field (and any source fields) to be makred
575             invalid B<if> required is true.
576              
577             =back
578              
579             An example:
580              
581             my $verifier = Data::Verifier->new(
582             profile => {
583             first_name => {
584             required => 1
585             },
586             last_name => {
587             required => 1
588             }
589             },
590             derived => {
591             'full_name' => {
592             required => 1,
593             fields => [qw(first_name last_name)],
594             deriver => sub {
595             my $r = shift;
596             return $r->get_value('first_name').' '.$r->get_value('last_name')
597             }
598             }
599             }
600             );
601              
602             In the above example a field named C<full_name> will be created that is
603             the other two fields concatenated. If the derived field is required and
604             C<deriver> subref returns undef then the derived field B<and> the fields
605             listed in C<fields> will also be invalid.
606              
607             =head2 filters
608              
609             An optional arrayref of filter names through which B<all> values will be
610             passed.
611              
612             =head2 profile
613              
614             The profile is a hashref. Each value you'd like to verify is a key. The
615             values specify all the options to use with the field. The available options
616             are:
617              
618             =over 4
619              
620             =item B<coerce>
621              
622             If true then the value will be given an opportunity to coerce via Moose's
623             type system. If this is set, coercion will be ignored.
624              
625             =item B<coercion>
626              
627             Set this attribute to the coercion defined for this type. If B<coerce> is
628             set this attribute will be ignored. See the C<coercion> method above.
629              
630             =item B<dependent>
631              
632             Allows a set of fields to be specifid as dependents of this one. The argument
633             for this key is a full-fledged profile as you would give to the profile key:
634              
635             my $verifier = Data::Verifier->new(
636             profile => {
637             password => {
638             dependent => {
639             password2 => {
640             required => 1,
641             }
642             }
643             }
644             }
645             );
646              
647             In the above example C<password> is not required. If it is provided then
648             password2 must also be provided. If any depedents of a field are missing or
649             invalid then that field is B<invalid>. In our example if password is provided
650             and password2 is missing then password will be invalid.
651              
652             =item B<filters>
653              
654             An optional list of filters through which this specific value will be run.
655             See the documentation for L<Data::Verifier::Filters> to learn more. This
656             value my be either a scalar (string or coderef) or an arrayref of strings or
657             coderefs.
658              
659             =item B<max_length>
660              
661             An optional length which the value may not exceed.
662              
663             =item B<min_length>
664              
665             An optional length which the value may not be less.
666              
667             =item B<member_post_check>
668              
669             A post check that is only to be applied to the members of an ArrayRef based
670             type. Because it is verified in something of a vacuum, the results object it
671             receives will have no other values to look at. Therefore member_post_check
672             is only useful if you want to do some sort of weird post-check thing that I
673             can't imagine would be a good idea.
674              
675             =item B<post_check>
676              
677             The C<post_check> key takes a subref and, after all verification has finished,
678             executes the subref with the results of the verification as it's only argument.
679             The subref's return value determines if the field to which the post_check
680             belongs is invalid. A typical example would be when the value of one field
681             must be equal to the other, like an email confirmation:
682              
683             my $verifier = Data::Verifier->new(
684             profile => {
685             email => {
686             required => 1,
687             dependent => {
688             email2 => {
689             required => 1,
690             }
691             },
692             post_check => sub {
693             my $r = shift;
694             return $r->get_value('email') eq $r->get_value('email2');
695             }
696             },
697             }
698             );
699              
700             my $results = $verifier->verify({
701             email => 'foo@example.com', email2 => 'foo2@example.com'
702             });
703              
704             $results->success; # false
705             $results->is_valid('email'); # false
706             $results->is_valid('email2'); # true, as it has no post_check
707              
708             In the above example, C<success> will return false, because the value of
709             C<email> does not match the value of C<email2>. C<is_valid> will return false
710             for C<email> but true for C<email2>, since nothing specifically invalidated it.
711             In this example you should rely on the C<email> field, as C<email2> carries no
712             significance but to confirm C<email>.
713              
714             B<Note about post_check and exceptions>: If have a more complex post_check
715             that could fail in multiple ways, you can C<die> in your post_check coderef
716             and the exception will be stored in the fields C<reason> attribute.
717              
718             B<Note about post_check and ArrayRef based types>: The post check is B<not>
719             executed for ArrayRef based types. See the note earlier in this documentation
720             about ArrayRefs.
721              
722             =item B<required>
723              
724             Determines if this field is required for verification.
725              
726             =item B<type>
727              
728             The name of the Moose type constraint to use with verifying this field's
729             value. Note, this will also accept an instance of
730             L<Moose::Meta::TypeConstraint>, although it may not serialize properly as a
731             result.
732              
733             =back
734              
735             =head1 METHODS
736              
737             =head2 coercion
738              
739             Define a coercion to use for verification. This will not define a global
740             Moose type coercion, but is instead just a single coercion to apply to a
741             specific entity.
742              
743             my $verifier = Data::Verifier->new(
744             profile => {
745             a_string => {
746             type => 'Str',
747             coercion => Data::Verifier::coercion(
748             from => 'Int',
749             via => sub { (qw[ one two three ])[ ($_ - 1) ] }
750             ),
751             },
752             }
753             );
754              
755             =head2 verify (\%parameters)
756              
757             Call this method and provide the parameters you are checking. The results
758             will be provided to you as a L<Data::Verifier::Results> object.
759              
760             =head1 CONTRIBUTORS
761              
762             Mike Eldridge
763              
764             George Hartzell
765              
766             Tomohiro Hosaka
767              
768             Stevan Little
769              
770             Jason May
771              
772             Dennis Schön
773              
774             J. Shirley
775              
776             Wallace Reis
777              
778             Mohammad S Anwar
779              
780             =head1 AUTHOR
781              
782             Cory G Watson <gphat@cpan.org>
783              
784             =head1 COPYRIGHT AND LICENSE
785              
786             This software is copyright (c) 2016 by Cold Hard Code, LLC.
787              
788             This is free software; you can redistribute it and/or modify it under
789             the same terms as the Perl 5 programming language system itself.
790              
791             =cut