|  line  | 
 stmt  | 
 bran  | 
 cond  | 
 sub  | 
 pod  | 
 time  | 
 code  | 
| 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 package Test::CPAN::Meta::YAML::Version;  | 
| 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
3
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
40226
 | 
 use warnings;  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
16
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
368
 | 
    | 
| 
4
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
48
 | 
 use strict;  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
329
 | 
    | 
| 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
6
 | 
10
 | 
 
 | 
 
 | 
  
10
  
 | 
 
 | 
46
 | 
 use vars qw($VERSION);  | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
    | 
| 
 
 | 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
34736
 | 
    | 
| 
7
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 $VERSION = '0.24';  | 
| 
8
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #----------------------------------------------------------------------------  | 
| 
10
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
11
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 NAME  | 
| 
12
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
13
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Test::CPAN::Meta::YAML::Version - Validate CPAN META data against the specification  | 
| 
14
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
15
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 SYNOPSIS  | 
| 
16
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
17
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   use Test::CPAN::Meta::YAML::Version;  | 
| 
18
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
19
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 DESCRIPTION  | 
| 
20
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
21
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This module was written to ensure that a META.yml file, provided with a  | 
| 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 standard distribution uploaded to CPAN, meets the specifications that are  | 
| 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 slowly being introduced to module uploads, via the use of  | 
| 
24
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 L, L and L.  | 
| 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
26
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 This module is meant to be used together with L, however  | 
| 
27
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the code is self contained enough that you can access it directly.  | 
| 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
29
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 See L for further details of the CPAN Meta Specification.  | 
| 
30
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
31
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 ABSTRACT  | 
| 
32
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
33
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validation of META.yml data against the CPAN Meta Specification.  | 
| 
34
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
35
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
36
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
37
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #----------------------------------------------------------------------------  | 
| 
38
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
39
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #############################################################################  | 
| 
40
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Specification Definitions                                                  #  | 
| 
41
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #############################################################################  | 
| 
42
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
43
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %known_specs = (  | 
| 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '1.4' => 'http://module-build.sourceforge.net/META-spec-v1.4.html',  | 
| 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '1.3' => 'http://module-build.sourceforge.net/META-spec-v1.3.html',  | 
| 
46
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '1.2' => 'http://module-build.sourceforge.net/META-spec-v1.2.html',  | 
| 
47
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '1.1' => 'http://module-build.sourceforge.net/META-spec-v1.1.html',  | 
| 
48
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     '1.0' => 'http://module-build.sourceforge.net/META-spec-v1.0.html'  | 
| 
49
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
50
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %known_urls = map {$known_specs{$_} => $_} keys %known_specs;  | 
| 
51
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
52
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $module_map1 = { 'map' => { ':key' => { name => \&module, value => \&exversion } } };  | 
| 
53
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $module_map2 = { 'map' => { ':key' => { name => \&module, value => \&version   } } };  | 
| 
54
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $no_index_1_3 = {  | 
| 
55
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { file       => { list => { value => \&string } },  | 
| 
56
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      directory  => { list => { value => \&string } },  | 
| 
57
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      'package'  => { list => { value => \&string } },  | 
| 
58
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      namespace  => { list => { value => \&string } },  | 
| 
59
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
60
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
61
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $no_index_1_2 = {  | 
| 
62
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { file       => { list => { value => \&string } },  | 
| 
63
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      dir        => { list => { value => \&string } },  | 
| 
64
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      'package'  => { list => { value => \&string } },  | 
| 
65
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      namespace  => { list => { value => \&string } },  | 
| 
66
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
67
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my $no_index_1_1 = {  | 
| 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { ':key'     => { name => \&keyword, list => { value => \&string } },  | 
| 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
71
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 };  | 
| 
72
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %definitions = (  | 
| 
74
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '1.4' => {  | 
| 
75
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  'header'              => { mandatory => 1, value => \&header },  | 
| 
76
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'meta-spec'           => { mandatory => 1, 'map' => { version => { mandatory => 1, value => \&version},  | 
| 
77
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                                         url     => { mandatory => 1, value => \&urlspec } } },  | 
| 
78
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
79
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'name'                => { mandatory => 1, value => \&string  },  | 
| 
80
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version'             => { mandatory => 1, value => \&version },  | 
| 
81
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'abstract'            => { mandatory => 1, value => \&string  },  | 
| 
82
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'author'              => { mandatory => 1, list  => { value => \&string } },  | 
| 
83
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license'             => { mandatory => 1, value => \&license },  | 
| 
84
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'generated_by'        => { mandatory => 1, value => \&string  },  | 
| 
85
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
86
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'distribution_type'   => { value => \&string  },  | 
| 
87
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'dynamic_config'      => { value => \&boolean },  | 
| 
88
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
89
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'requires'            => $module_map1,  | 
| 
90
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'recommends'          => $module_map1,  | 
| 
91
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'build_requires'      => $module_map1,  | 
| 
92
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'configure_requires'  => $module_map1,  | 
| 
93
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'conflicts'           => $module_map2,  | 
| 
94
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
95
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'optional_features'   => {  | 
| 
96
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => {  | 
| 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ':key'  => { name => \&identifier,  | 
| 
98
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'map'   => { description        => { value => \&string },  | 
| 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_packages  => { value => \&string },  | 
| 
100
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_os        => { value => \&string },  | 
| 
101
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          excludes_os        => { value => \&string },  | 
| 
102
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires           => $module_map1,  | 
| 
103
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          recommends         => $module_map1,  | 
| 
104
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          build_requires     => $module_map1,  | 
| 
105
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          conflicts          => $module_map2,  | 
| 
106
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
107
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
108
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
109
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
110
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
111
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'provides'    => {  | 
| 
112
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { ':key' => { name  => \&module,  | 
| 
113
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                  'map' => { file    => { mandatory => 1, value => \&file },  | 
| 
114
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                             version => { value => \&version } } } }  | 
| 
115
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
116
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
117
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'no_index'    => $no_index_1_3,  | 
| 
118
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'private'     => $no_index_1_3,  | 
| 
119
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
120
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'keywords'    => { list => { value => \&string } },  | 
| 
121
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
122
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'resources'   => {  | 
| 
123
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { license    => { value => \&url },  | 
| 
124
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      homepage   => { value => \&url },  | 
| 
125
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      bugtracker => { value => \&url },  | 
| 
126
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      repository => { value => \&url },  | 
| 
127
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      ':key'     => { value => \&string, name => \&resource },  | 
| 
128
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
129
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
130
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
131
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # additional user defined key/value pairs  | 
| 
132
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # note we can only validate the key name, as the structure is user defined  | 
| 
133
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':key'        => { name => \&keyword, value => \&anything },  | 
| 
134
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 },  | 
| 
135
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
136
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '1.3' => {  | 
| 
137
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  'header'              => { mandatory => 1, value => \&header },  | 
| 
138
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'meta-spec'           => { mandatory => 1, 'map' => { version => { mandatory => 1, value => \&version},  | 
| 
139
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                                         url     => { mandatory => 1, value => \&urlspec } } },  | 
| 
140
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
141
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'name'                => { mandatory => 1, value => \&string  },  | 
| 
142
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version'             => { mandatory => 1, value => \&version },  | 
| 
143
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'abstract'            => { mandatory => 1, value => \&string  },  | 
| 
144
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'author'              => { mandatory => 1, list  => { value => \&string } },  | 
| 
145
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license'             => { mandatory => 1, value => \&license },  | 
| 
146
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'generated_by'        => { mandatory => 1, value => \&string  },  | 
| 
147
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
148
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'distribution_type'   => { value => \&string  },  | 
| 
149
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'dynamic_config'      => { value => \&boolean },  | 
| 
150
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
151
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'requires'            => $module_map1,  | 
| 
152
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'recommends'          => $module_map1,  | 
| 
153
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'build_requires'      => $module_map1,  | 
| 
154
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'conflicts'           => $module_map2,  | 
| 
155
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
156
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'optional_features'   => {  | 
| 
157
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => {  | 
| 
158
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ':key'  => { name => \&identifier,  | 
| 
159
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'map'   => { description        => { value => \&string },  | 
| 
160
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_packages  => { value => \&string },  | 
| 
161
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_os        => { value => \&string },  | 
| 
162
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          excludes_os        => { value => \&string },  | 
| 
163
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires           => $module_map1,  | 
| 
164
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          recommends         => $module_map1,  | 
| 
165
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          build_requires     => $module_map1,  | 
| 
166
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          conflicts          => $module_map2,  | 
| 
167
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
168
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
169
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
170
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
171
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
172
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'provides'    => {  | 
| 
173
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { ':key' => { name  => \&module,  | 
| 
174
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                  'map' => { file    => { mandatory => 1, value => \&file },  | 
| 
175
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                             version => { value => \&version } } } }  | 
| 
176
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
177
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
178
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'no_index'    => $no_index_1_3,  | 
| 
179
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'private'     => $no_index_1_3,  | 
| 
180
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
181
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'keywords'    => { list => { value => \&string } },  | 
| 
182
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
183
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'resources'   => {  | 
| 
184
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { license    => { value => \&url },  | 
| 
185
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      homepage   => { value => \&url },  | 
| 
186
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      bugtracker => { value => \&url },  | 
| 
187
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      repository => { value => \&url },  | 
| 
188
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      ':key'     => { value => \&string, name => \&resource },  | 
| 
189
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
190
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
191
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
192
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # additional user defined key/value pairs  | 
| 
193
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # note we can only validate the key name, as the structure is user defined  | 
| 
194
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':key'        => { name => \&keyword, value => \&anything },  | 
| 
195
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 },  | 
| 
196
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
197
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # v1.2 is misleading, it seems to assume that a number of fields where created  | 
| 
198
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # within v1.1, when they were created within v1.2. This may have been an  | 
| 
199
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # original mistake, and that a v1.1 was retro fitted into the timeline, when  | 
| 
200
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # v1.2 was originally slated as v1.1. But I could be wrong ;)  | 
| 
201
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '1.2' => {  | 
| 
202
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  'header'              => { mandatory => 1, value => \&header },  | 
| 
203
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'meta-spec'           => { mandatory => 1, 'map' => { version => { mandatory => 1, value => \&version},  | 
| 
204
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                                         url     => { mandatory => 1, value => \&urlspec } } },  | 
| 
205
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
206
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'name'                => { mandatory => 1, value => \&string  },  | 
| 
207
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version'             => { mandatory => 1, value => \&version },  | 
| 
208
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license'             => { mandatory => 1, value => \&license },  | 
| 
209
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'generated_by'        => { mandatory => 1, value => \&string  },  | 
| 
210
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'author'              => { mandatory => 1, list => { value => \&string } },  | 
| 
211
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'abstract'            => { mandatory => 1, value => \&string  },  | 
| 
212
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
213
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'distribution_type'   => { value => \&string  },  | 
| 
214
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'dynamic_config'      => { value => \&boolean },  | 
| 
215
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
216
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'keywords'            => { list => { value => \&string } },  | 
| 
217
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'private'             => $no_index_1_2,  | 
| 
219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   '$no_index'           => $no_index_1_2,  | 
| 
220
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
221
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'requires'            => $module_map1,  | 
| 
222
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'recommends'          => $module_map1,  | 
| 
223
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'build_requires'      => $module_map1,  | 
| 
224
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'conflicts'           => $module_map2,  | 
| 
225
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
226
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'optional_features'   => {  | 
| 
227
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => {  | 
| 
228
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         ':key'  => { name => \&identifier,  | 
| 
229
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             'map'   => { description        => { value => \&string },  | 
| 
230
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_packages  => { value => \&string },  | 
| 
231
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires_os        => { value => \&string },  | 
| 
232
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          excludes_os        => { value => \&string },  | 
| 
233
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          requires           => $module_map1,  | 
| 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          recommends         => $module_map1,  | 
| 
235
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          build_requires     => $module_map1,  | 
| 
236
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                          conflicts          => $module_map2,  | 
| 
237
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
238
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
239
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
      }  | 
| 
240
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
241
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
242
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'provides'    => {  | 
| 
243
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { ':key' => { name  => \&module,  | 
| 
244
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                  'map' => { file    => { mandatory => 1, value => \&file },  | 
| 
245
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                                             version => { value => \&version } } } }  | 
| 
246
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
247
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
248
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'resources'   => {  | 
| 
249
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'map'       => { license    => { value => \&url },  | 
| 
250
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      homepage   => { value => \&url },  | 
| 
251
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      bugtracker => { value => \&url },  | 
| 
252
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      repository => { value => \&url },  | 
| 
253
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
                      ':key'     => { value => \&string, name => \&resource },  | 
| 
254
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
255
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   },  | 
| 
256
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
257
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # additional user defined key/value pairs  | 
| 
258
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # note we can only validate the key name, as the structure is user defined  | 
| 
259
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':key'        => { name => \&keyword, value => \&anything },  | 
| 
260
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 },  | 
| 
261
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
262
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # note that the 1.1 spec doesn't specify optional or mandatory fields, what  | 
| 
263
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # appears below is assumed from later specifications.  | 
| 
264
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '1.1' => {  | 
| 
265
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  'header'              => { mandatory => 1, value => \&header },  | 
| 
266
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'name'                => { mandatory => 1, value => \&string  },  | 
| 
267
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version'             => { mandatory => 1, value => \&version },  | 
| 
268
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license'             => { mandatory => 1, value => \&license },  | 
| 
269
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license_uri'         => { mandatory => 0, value => \&url },  | 
| 
270
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'generated_by'        => { mandatory => 1, value => \&string  },  | 
| 
271
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
272
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'distribution_type'   => { value => \&string  },  | 
| 
273
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'dynamic_config'      => { value => \&boolean },  | 
| 
274
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
275
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'private'             => $no_index_1_1,  | 
| 
276
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
277
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'requires'            => $module_map1,  | 
| 
278
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'recommends'          => $module_map1,  | 
| 
279
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'build_requires'      => $module_map1,  | 
| 
280
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'conflicts'           => $module_map2,  | 
| 
281
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
282
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # additional user defined key/value pairs  | 
| 
283
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # note we can only validate the key name, as the structure is user defined  | 
| 
284
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':key'        => { name => \&keyword, value => \&anything },  | 
| 
285
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 },  | 
| 
286
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
287
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # note that the 1.0 spec doesn't specify optional or mandatory fields, what  | 
| 
288
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 # appears below is assumed from later specifications.  | 
| 
289
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 '1.0' => {  | 
| 
290
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #  'header'              => { mandatory => 1, value => \&header },  | 
| 
291
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'name'                => { mandatory => 1, value => \&string  },  | 
| 
292
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'version'             => { mandatory => 1, value => \&version },  | 
| 
293
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'license'             => { mandatory => 1, value => \&license },  | 
| 
294
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'generated_by'        => { mandatory => 1, value => \&string  },  | 
| 
295
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
296
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'distribution_type'   => { value => \&string  },  | 
| 
297
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'dynamic_config'      => { value => \&boolean },  | 
| 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
299
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'requires'            => $module_map1,  | 
| 
300
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'recommends'          => $module_map1,  | 
| 
301
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'build_requires'      => $module_map1,  | 
| 
302
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   'conflicts'           => $module_map2,  | 
| 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
304
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # additional user defined key/value pairs  | 
| 
305
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   # note we can only validate the key name, as the structure is user defined  | 
| 
306
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
   ':key'        => { name => \&keyword, value => \&anything },  | 
| 
307
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 },  | 
| 
308
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
309
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
310
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #############################################################################  | 
| 
311
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #Code                                                                       #  | 
| 
312
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 #############################################################################  | 
| 
313
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
314
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 CLASS CONSTRUCTOR  | 
| 
315
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
316
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
317
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
318
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * new( data => $data [, spec => $version] )  | 
| 
319
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
320
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 The constructor must be passed a valid data structure.  | 
| 
321
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
322
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Optionally you may also provide a specification version. This version is then  | 
| 
323
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 use to ensure that the given data structure meets the respective  | 
| 
324
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 specification definition. If no version is provided the module will attempt to  | 
| 
325
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 deduce the appropriate specification version from the data structure itself.  | 
| 
326
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
327
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
328
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
329
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
330
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
331
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub new {  | 
| 
332
 | 
45
 | 
 
 | 
 
 | 
  
45
  
 | 
  
1
  
 | 
32450
 | 
     my ($class,%hash) = @_;  | 
| 
333
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
334
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # create an attributes hash  | 
| 
335
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
140
 | 
     my $atts = {  | 
| 
336
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'spec' => $hash{spec},  | 
| 
337
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         'data' => $hash{data},  | 
| 
338
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     };  | 
| 
339
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
340
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     # create the object  | 
| 
341
 | 
45
 | 
 
 | 
 
 | 
 
 | 
 
 | 
155
 | 
     my $self = bless $atts, $class;  | 
| 
342
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
343
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
344
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head1 METHODS  | 
| 
345
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Main Methods  | 
| 
347
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
348
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
349
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
350
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * parse()  | 
| 
351
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
352
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Using the given data structure provided with the constructor, attempts to  | 
| 
353
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 parse and validate according to the appropriate specification definition.  | 
| 
354
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
355
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns 1 if any errors found, otherwise returns 0.  | 
| 
356
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
357
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * errors()  | 
| 
358
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
359
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Returns a list of the errors found during parsing.  | 
| 
360
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
361
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
362
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
363
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
364
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
365
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub parse {  | 
| 
366
 | 
44
 | 
 
 | 
 
 | 
  
44
  
 | 
  
1
  
 | 
103
 | 
     my $self = shift;  | 
| 
367
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
     my $data = $self->{data};  | 
| 
368
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
369
 | 
44
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
100
 | 
     unless($self->{spec}) {  | 
| 
370
 | 
21
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
127
 | 
         $self->{spec} = $data->{'meta-spec'} && $data->{'meta-spec'}{'version'} ? $data->{'meta-spec'}{'version'} : '1.0';  | 
| 
371
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
372
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
373
 | 
44
 | 
 
 | 
 
 | 
 
 | 
 
 | 
112
 | 
     $self->check_map($definitions{$self->{spec}},$data);  | 
| 
374
 | 
44
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
201
 | 
     return defined $self->{errors} ? 1 : 0;  | 
| 
375
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
376
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
377
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub errors {  | 
| 
378
 | 
41
 | 
 
 | 
 
 | 
  
41
  
 | 
  
1
  
 | 
166
 | 
     my $self = shift;  | 
| 
379
 | 
41
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
106
 | 
     return ()   unless($self->{errors});  | 
| 
380
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     return @{$self->{errors}};  | 
| 
 
 | 
23
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
    | 
| 
381
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
382
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
383
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Check Methods  | 
| 
384
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
385
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
386
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
387
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * check_map($spec,$data)  | 
| 
388
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
389
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Checks whether a map (or hash) part of the data structure conforms to the  | 
| 
390
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 appropriate specification definition.  | 
| 
391
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
392
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * check_list($spec,$data)  | 
| 
393
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
394
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Checks whether a list (or array) part of the data structure conforms to  | 
| 
395
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 the appropriate specification definition.  | 
| 
396
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
397
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
398
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
399
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
400
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
401
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub check_map {  | 
| 
402
 | 
350
 | 
 
 | 
 
 | 
  
350
  
 | 
  
1
  
 | 
775
 | 
     my ($self,$spec,$data) = @_;  | 
| 
403
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
404
 | 
350
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
635
 | 
     if(ref($spec) ne 'HASH') {  | 
| 
405
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         $self->_error( "Unknown META.yml specification, cannot validate." );  | 
| 
406
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         return;  | 
| 
407
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
408
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
409
 | 
349
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
504
 | 
     if(ref($data) ne 'HASH') {  | 
| 
410
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
         $self->_error( "Expected a map structure from data string or file." );  | 
| 
411
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
         return;  | 
| 
412
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
413
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
414
 | 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
715
 | 
     for my $key (keys %$spec) {  | 
| 
415
 | 
1350
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2341
 | 
         next    unless($spec->{$key}->{mandatory});  | 
| 
416
 | 
419
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
736
 | 
         next    if(defined $data->{$key});  | 
| 
417
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
         push @{$self->{stack}}, $key;  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
    | 
| 
418
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
         $self->_error( "Missing mandatory field, '$key'" );  | 
| 
419
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         pop @{$self->{stack}};  | 
| 
 
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
    | 
| 
420
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
421
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
422
 | 
346
 | 
 
 | 
 
 | 
 
 | 
 
 | 
753
 | 
     for my $key (keys %$data) {  | 
| 
423
 | 
1219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
922
 | 
         push @{$self->{stack}}, $key;  | 
| 
 
 | 
1219
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1530
 | 
    | 
| 
424
 | 
1219
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2275
 | 
         if($spec->{$key}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
425
 | 
783
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
1332
 | 
             if($spec->{$key}{value}) {  | 
| 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
426
 | 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
782
 | 
                 $spec->{$key}{value}->($self,$key,$data->{$key});  | 
| 
427
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif($spec->{$key}{'map'}) {  | 
| 
428
 | 
234
 | 
 
 | 
 
 | 
 
 | 
 
 | 
432
 | 
                 $self->check_map($spec->{$key}{'map'},$data->{$key});  | 
| 
429
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif($spec->{$key}{'list'}) {  | 
| 
430
 | 
69
 | 
 
 | 
 
 | 
 
 | 
 
 | 
134
 | 
                 $self->check_list($spec->{$key}{'list'},$data->{$key});  | 
| 
431
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
432
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
433
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($spec->{':key'}) {  | 
| 
434
 | 
436
 | 
 
 | 
 
 | 
 
 | 
 
 | 
647
 | 
             $spec->{':key'}{name}->($self,$key,$key);  | 
| 
435
 | 
436
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
705
 | 
             if($spec->{':key'}{value}) {  | 
| 
 
 | 
 
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
436
 | 
366
 | 
 
 | 
 
 | 
 
 | 
 
 | 
573
 | 
                 $spec->{':key'}{value}->($self,$key,$data->{$key});  | 
| 
437
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif($spec->{':key'}{'map'}) {  | 
| 
438
 | 
70
 | 
 
 | 
 
 | 
 
 | 
 
 | 
152
 | 
                 $self->check_map($spec->{':key'}{'map'},$data->{$key});  | 
| 
439
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             } elsif($spec->{':key'}{'list'}) {  | 
| 
440
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
                 $self->check_list($spec->{':key'}{'list'},$data->{$key});  | 
| 
441
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
             }  | 
| 
442
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
443
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
444
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->_error( "Unknown key, '$key', found in map structure" );  | 
| 
445
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
446
 | 
1218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
928
 | 
         pop @{$self->{stack}};  | 
| 
 
 | 
1218
 | 
 
 | 
 
 | 
 
 | 
 
 | 
1832
 | 
    | 
| 
447
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
448
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
449
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
450
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub check_list {  | 
| 
451
 | 
71
 | 
 
 | 
 
 | 
  
71
  
 | 
  
1
  
 | 
1002
 | 
     my ($self,$spec,$data) = @_;  | 
| 
452
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
453
 | 
71
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
160
 | 
     if(ref($data) ne 'ARRAY') {  | 
| 
454
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
         $self->_error( "Expected a list structure" );  | 
| 
455
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
         return;  | 
| 
456
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
457
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
458
 | 
68
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
125
 | 
     if(defined $spec->{mandatory}) {  | 
| 
459
 | 
0
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
0
 | 
         if(!defined $data->[0]) {  | 
| 
460
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->_error( "Missing entries from mandatory list" );  | 
| 
461
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
462
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
463
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
464
 | 
68
 | 
 
 | 
 
 | 
 
 | 
 
 | 
90
 | 
     for my $value (@$data) {  | 
| 
465
 | 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
84
 | 
         push @{$self->{stack}}, $value;  | 
| 
 
 | 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
133
 | 
    | 
| 
466
 | 
99
 | 
  
 50
  
 | 
 
 | 
 
 | 
 
 | 
158
 | 
         if(defined $spec->{value}) {  | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
 
 | 
 
 | 
  
  0
  
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
467
 | 
99
 | 
 
 | 
 
 | 
 
 | 
 
 | 
168
 | 
             $spec->{value}->($self,'list',$value);  | 
| 
468
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif(defined $spec->{'map'}) {  | 
| 
469
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->check_map($spec->{'map'},$value);  | 
| 
470
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif(defined $spec->{'list'}) {  | 
| 
471
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->check_list($spec->{'list'},$value);  | 
| 
472
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
473
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } elsif ($spec->{':key'}) {  | 
| 
474
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->check_map($spec,$value);  | 
| 
475
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
476
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         } else {  | 
| 
477
 | 
0
 | 
 
 | 
 
 | 
 
 | 
 
 | 
0
 | 
             $self->_error( "Unknown value type, '$value', found in list structure" );  | 
| 
478
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
479
 | 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
73
 | 
         pop @{$self->{stack}};  | 
| 
 
 | 
97
 | 
 
 | 
 
 | 
 
 | 
 
 | 
210
 | 
    | 
| 
480
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
481
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
482
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
483
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =head2 Validator Methods  | 
| 
484
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
485
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =over  | 
| 
486
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
487
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * header($self,$key,$value)  | 
| 
488
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
489
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that the YAML header is valid.  | 
| 
490
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
491
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Note: No longer used as we now read the YAML data structure, not the file.  | 
| 
492
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
493
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * url($self,$key,$value)  | 
| 
494
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
495
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that a given value is in an acceptable URL format  | 
| 
496
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
497
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * urlspec($self,$key,$value)  | 
| 
498
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
499
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that the URL to a META.yml specification is a known one.  | 
| 
500
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
501
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * string_or_undef($self,$key,$value)  | 
| 
502
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
503
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that the value is either a string or an undef value. Bit of a  | 
| 
504
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 catchall function for parts of the data structure that are completely user  | 
| 
505
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 defined.  | 
| 
506
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
507
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * string($self,$key,$value)  | 
| 
508
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
509
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that a string exists for the given key.  | 
| 
510
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
511
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * file($self,$key,$value)  | 
| 
512
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
513
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validate that a file is passed for the given key. This may be made more  | 
| 
514
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 thorough in the future. For now it acts like \&string.  | 
| 
515
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
516
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * exversion($self,$key,$value)  | 
| 
517
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
518
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates a list of versions, e.g. '<= 5, >=2, ==3, !=4, >1, <6, 0'.  | 
| 
519
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
520
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * version($self,$key,$value)  | 
| 
521
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
522
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates a single version string. Versions of the type '5.8.8' and '0.00_00'  | 
| 
523
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 are both valid. A leading 'v' like 'v1.2.3' is also valid.  | 
| 
524
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
525
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * boolean($self,$key,$value)  | 
| 
526
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
527
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates for a boolean value. Currently these values are '1', '0', 'true',  | 
| 
528
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 'false', however the latter 2 may be removed.  | 
| 
529
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
530
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * license($self,$key,$value)  | 
| 
531
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
532
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that a value is given for the license. Returns 1 if an known license  | 
| 
533
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 type, or 2 if a value is given but the license type is not a recommended one.  | 
| 
534
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
535
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * resource($self,$key,$value)  | 
| 
536
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
537
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that the given key is in CamelCase, to indicate a user defined  | 
| 
538
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 keyword.  | 
| 
539
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
540
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * keyword($self,$key,$value)  | 
| 
541
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
542
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that key is in an acceptable format for the META.yml specification,  | 
| 
543
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 i.e. any in the character class [-_a-z].  | 
| 
544
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
545
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 For user defined keys, although not explicitly stated in the specifications  | 
| 
546
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 (v1.0 - v1.4), the convention is to precede the key with a pattern matching  | 
| 
547
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 qr{\Ax_}i. Following this any character from the character class [-_a-zA-Z]  | 
| 
548
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 can be used. This clarification has been added to v2.0 of the specification.  | 
| 
549
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
550
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * identifier($self,$key,$value)  | 
| 
551
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
552
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that key is in an acceptable format for the META.yml specification,  | 
| 
553
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 for an identifier, i.e. any that matches the regular expression  | 
| 
554
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 qr/[a-z][a-z_]/i.  | 
| 
555
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
556
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * module($self,$key,$value)  | 
| 
557
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
558
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Validates that a given key is in an acceptable module name format, e.g.  | 
| 
559
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 'Test::CPAN::Meta::YAML::Version'.  | 
| 
560
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
561
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =item * anything($self,$key,$value)  | 
| 
562
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
563
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 Usually reserved for user defined structures, allowing them to be considered  | 
| 
564
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 valid without a need for a specification definition for the structure.  | 
| 
565
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
566
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =back  | 
| 
567
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
568
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 =cut  | 
| 
569
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
570
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub header {  | 
| 
571
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
15
 | 
     my ($self,$key,$value) = @_;  | 
| 
572
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     if(defined $value) {  | 
| 
573
 | 
3
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
30
 | 
         return 1    if($value && $value =~ /^--- #YAML:1.0/);  | 
| 
574
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
575
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     $self->_error( "file does not have a valid YAML header." );  | 
| 
576
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     return 0;  | 
| 
577
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
578
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
579
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _uri_split {  | 
| 
580
 | 
28
 | 
 
 | 
 
 | 
  
28
  
 | 
 
 | 
149
 | 
      return $_[0] =~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?,;  | 
| 
581
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
582
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
583
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub url {  | 
| 
584
 | 
30
 | 
 
 | 
 
 | 
  
30
  
 | 
  
1
  
 | 
45
 | 
     my ($self,$key,$value) = @_;  | 
| 
585
 | 
30
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
47
 | 
     if($value) {  | 
| 
586
 | 
28
 | 
 
 | 
 
 | 
 
 | 
 
 | 
49
 | 
         my ($scheme, $auth, $path, $query, $frag) = _uri_split($value);  | 
| 
587
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
588
 | 
28
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
60
 | 
         unless ( $scheme ) {  | 
| 
589
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
             $self->_error( "'$value' for '$key' does not have a URL scheme" );  | 
| 
590
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
9
 | 
             return 0;  | 
| 
591
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
592
 | 
26
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
41
 | 
         unless ( $auth ) {  | 
| 
593
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
22
 | 
             $self->_error(  "'$value' for '$key' does not have a URL authority" );  | 
| 
594
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
             return 0;  | 
| 
595
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
596
 | 
22
 | 
 
 | 
 
 | 
 
 | 
 
 | 
37
 | 
         return 1;  | 
| 
597
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
598
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         $value = '';  | 
| 
599
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
600
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $self->_error( "'$value' for '$key' is not a valid URL." );  | 
| 
601
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
11
 | 
     return 0;  | 
| 
602
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
603
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
604
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub urlspec {  | 
| 
605
 | 
40
 | 
 
 | 
 
 | 
  
40
  
 | 
  
1
  
 | 
53
 | 
     my ($self,$key,$value) = @_;  | 
| 
606
 | 
40
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
79
 | 
     if(defined $value) {  | 
| 
607
 | 
39
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
227
 | 
         return 1    if($value && $known_specs{$self->{spec}} eq $value);  | 
| 
608
 | 
8
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
44
 | 
         if($value && $known_urls{$value}) {  | 
| 
609
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
             $self->_error( 'META.yml specification URL does not match version' );  | 
| 
610
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
550
 | 
             return 0;  | 
| 
611
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         }  | 
| 
612
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
613
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     $self->_error( 'Unknown META.yml specification' );  | 
| 
614
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     return 0;  | 
| 
615
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
616
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
617
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub string {  | 
| 
618
 | 
271
 | 
 
 | 
 
 | 
  
271
  
 | 
  
1
  
 | 
292
 | 
     my ($self,$key,$value) = @_;  | 
| 
619
 | 
271
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
454
 | 
     if(defined $value) {  | 
| 
620
 | 
270
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
607
 | 
         return 1    if($value || $value =~ /^0$/);  | 
| 
621
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
622
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
     $self->_error( "value is an undefined string" );  | 
| 
623
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
8
 | 
     return 0;  | 
| 
624
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
625
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
626
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub string_or_undef {  | 
| 
627
 | 
4
 | 
 
 | 
 
 | 
  
4
  
 | 
  
1
  
 | 
10
 | 
     my ($self,$key,$value) = @_;  | 
| 
628
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
16
 | 
     return 1    unless(defined $value);  | 
| 
629
 | 
3
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
26
 | 
     return 1    if($value || $value =~ /^0$/);  | 
| 
630
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
6
 | 
     $self->_error( "No string defined for '$key'" );  | 
| 
631
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return 0;  | 
| 
632
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
633
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
634
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub file {  | 
| 
635
 | 
69
 | 
 
 | 
 
 | 
  
69
  
 | 
  
1
  
 | 
140
 | 
     my ($self,$key,$value) = @_;  | 
| 
636
 | 
69
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
158
 | 
     return 1    if(defined $value);  | 
| 
637
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
7
 | 
     $self->_error( "No file defined for '$key'" );  | 
| 
638
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
4
 | 
     return 0;  | 
| 
639
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
640
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
641
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub exversion {  | 
| 
642
 | 
301
 | 
 
 | 
 
 | 
  
301
  
 | 
  
1
  
 | 
309
 | 
     my ($self,$key,$value) = @_;  | 
| 
643
 | 
301
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
957
 | 
     if(defined $value && ($value || $value =~ /0/)) {  | 
| 
 
 | 
 
 | 
 
 | 
  
 66
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
644
 | 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
273
 | 
         my $pass = 1;  | 
| 
645
 | 
298
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
537
 | 
         for(split(",",$value)) { $self->version($key,$_) or ($pass = 0); }  | 
| 
 
 | 
303
 | 
 
 | 
 
 | 
 
 | 
 
 | 
410
 | 
    | 
| 
646
 | 
298
 | 
 
 | 
 
 | 
 
 | 
 
 | 
426
 | 
         return $pass;  | 
| 
647
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
648
 | 
3
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
9
 | 
     $value = ''  unless(defined $value);  | 
| 
649
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
14
 | 
     $self->_error( "'$value' for '$key' is not a valid version." );  | 
| 
650
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     return 0;  | 
| 
651
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
652
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
653
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub version {  | 
| 
654
 | 
459
 | 
 
 | 
 
 | 
  
459
  
 | 
  
1
  
 | 
516
 | 
     my ($self,$key,$value) = @_;  | 
| 
655
 | 
459
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
564
 | 
     if(defined $value) {  | 
| 
656
 | 
457
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
946
 | 
         return 0    unless($value || $value =~ /0/);  | 
| 
657
 | 
456
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
2406
 | 
         return 1    if($value =~ /^\s*((<|<=|>=|>|!=|==)\s*)?v?\d+((\.\d+((_|\.)\d+)?)?)/);  | 
| 
658
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
659
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $value = '';  | 
| 
660
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
661
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
29
 | 
     $self->_error( "'$value' for '$key' is not a valid version." );  | 
| 
662
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
21
 | 
     return 0;  | 
| 
663
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
664
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
665
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub boolean {  | 
| 
666
 | 
8
 | 
 
 | 
 
 | 
  
8
  
 | 
  
1
  
 | 
21
 | 
     my ($self,$key,$value) = @_;  | 
| 
667
 | 
8
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
20
 | 
     if(defined $value) {  | 
| 
668
 | 
6
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
42
 | 
         return 1    if($value =~ /^(0|1|true|false)$/);  | 
| 
669
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
670
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
5
 | 
         $value = '';  | 
| 
671
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
672
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     $self->_error( "'$value' for '$key' is not a boolean value." );  | 
| 
673
 | 
4
 | 
 
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     return 0;  | 
| 
674
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
675
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
676
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 my %licenses = (  | 
| 
677
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'perl'         => 'http://dev.perl.org/licenses/',  | 
| 
678
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'gpl'          => 'http://www.opensource.org/licenses/gpl-license.php',  | 
| 
679
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'apache'       => 'http://apache.org/licenses/LICENSE-2.0',  | 
| 
680
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'artistic'     => 'http://opensource.org/licenses/artistic-license.php',  | 
| 
681
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'artistic2'    => 'http://opensource.org/licenses/artistic-license-2.0.php',  | 
| 
682
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'artistic-2.0' => 'http://opensource.org/licenses/artistic-license-2.0.php',  | 
| 
683
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'lgpl'         => 'http://www.opensource.org/licenses/lgpl-license.phpt',  | 
| 
684
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'bsd'          => 'http://www.opensource.org/licenses/bsd-license.php',  | 
| 
685
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'gpl'          => 'http://www.opensource.org/licenses/gpl-license.php',  | 
| 
686
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'mit'          => 'http://opensource.org/licenses/mit-license.php',  | 
| 
687
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'mozilla'      => 'http://opensource.org/licenses/mozilla1.1.php',  | 
| 
688
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'open_source'  => undef,  | 
| 
689
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'unrestricted' => undef,  | 
| 
690
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'restrictive'  => undef,  | 
| 
691
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     'unknown'      => undef,  | 
| 
692
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 );  | 
| 
693
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
694
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub license {  | 
| 
695
 | 
61
 | 
 
 | 
 
 | 
  
61
  
 | 
  
1
  
 | 
6455
 | 
     my ($self,$key,$value) = @_;  | 
| 
696
 | 
61
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
105
 | 
     if(defined $value) {  | 
| 
697
 | 
60
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
329
 | 
         return 1    if($value && exists $licenses{$value});  | 
| 
698
 | 
4
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
18
 | 
         return 2    if($value);  | 
| 
699
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
700
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $value = '';  | 
| 
701
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
702
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
12
 | 
     $self->_error( "License '$value' is unknown" );  | 
| 
703
 | 
2
 | 
 
 | 
 
 | 
 
 | 
 
 | 
10
 | 
     return 0;  | 
| 
704
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
705
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
706
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub resource {  | 
| 
707
 | 
7
 | 
 
 | 
 
 | 
  
7
  
 | 
  
1
  
 | 
18
 | 
     my ($self,$key) = @_;  | 
| 
708
 | 
7
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
17
 | 
     if(defined $key) {  | 
| 
709
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # a valid user defined key should be alphabetic  | 
| 
710
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
         # and contain at least one capital case letter.  | 
| 
711
 | 
6
 | 
  
100
  
 | 
  
 66
  
 | 
 
 | 
 
 | 
81
 | 
         return 1    if($key && $key =~ /^[a-z]+$/i && $key =~ /[A-Z]/);  | 
| 
 
 | 
 
 | 
 
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
712
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
713
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $key = '';  | 
| 
714
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
715
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
15
 | 
     $self->_error( "Resource '$key' must be in CamelCase." );  | 
| 
716
 | 
3
 | 
 
 | 
 
 | 
 
 | 
 
 | 
13
 | 
     return 0;  | 
| 
717
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
718
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
719
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub keyword {  | 
| 
720
 | 
80
 | 
 
 | 
 
 | 
  
80
  
 | 
  
1
  
 | 
4034
 | 
     my ($self,$key) = @_;  | 
| 
721
 | 
80
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
128
 | 
     if(defined $key) {  | 
| 
722
 | 
79
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
488
 | 
         return 1    if($key && $key =~ /^([a-z][-_a-z]*)$/);    # spec defined  | 
| 
723
 | 
6
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
39
 | 
         return 1    if($key && $key =~ /^x_([a-z][-_a-z]*)$/i); # user defined  | 
| 
724
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
725
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         $key = '';  | 
| 
726
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
727
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
25
 | 
     $self->_error( "Key '$key' is not a legal keyword." );  | 
| 
728
 | 
6
 | 
 
 | 
 
 | 
 
 | 
 
 | 
27
 | 
     return 0;  | 
| 
729
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
730
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
731
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub identifier {  | 
| 
732
 | 
13
 | 
 
 | 
 
 | 
  
13
  
 | 
  
1
  
 | 
3961
 | 
     my ($self,$key) = @_;  | 
| 
733
 | 
13
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
35
 | 
     if(defined $key) {  | 
| 
734
 | 
12
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
121
 | 
         return 1    if($key && $key =~ /^([a-z][_a-z]+)$/i);    # spec 2.0 defined  | 
| 
735
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
736
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
3
 | 
         $key = '';  | 
| 
737
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
738
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
19
 | 
     $self->_error( "Key '$key' is not a legal identifier." );  | 
| 
739
 | 
5
 | 
 
 | 
 
 | 
 
 | 
 
 | 
23
 | 
     return 0;  | 
| 
740
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
741
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
742
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub module {  | 
| 
743
 | 
370
 | 
 
 | 
 
 | 
  
370
  
 | 
  
1
  
 | 
345
 | 
     my ($self,$key) = @_;  | 
| 
744
 | 
370
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
493
 | 
     if(defined $key) {  | 
| 
745
 | 
369
 | 
  
100
  
 | 
  
100
  
 | 
 
 | 
 
 | 
2140
 | 
         return 1    if($key && $key =~ /^[A-Za-z0-9_]+(::[A-Za-z0-9_]+)*$/);  | 
| 
746
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     } else {  | 
| 
747
 | 
1
 | 
 
 | 
 
 | 
 
 | 
 
 | 
2
 | 
         $key = '';  | 
| 
748
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
     }  | 
| 
749
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
31
 | 
     $self->_error( "Key '$key' is not a legal module name." );  | 
| 
750
 | 
9
 | 
 
 | 
 
 | 
 
 | 
 
 | 
24
 | 
     return 0;  | 
| 
751
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
752
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
753
 | 
69
 | 
 
 | 
 
 | 
  
69
  
 | 
  
1
  
 | 
72
 | 
 sub anything { return 1 }  | 
| 
754
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
755
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 sub _error {  | 
| 
756
 | 
73
 | 
 
 | 
 
 | 
  
73
  
 | 
 
 | 
100
 | 
     my $self = shift;  | 
| 
757
 | 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
81
 | 
     my $mess = shift;  | 
| 
758
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
759
 | 
73
 | 
  
100
  
 | 
 
 | 
 
 | 
 
 | 
224
 | 
     $mess .= ' ('.join(' -> ',@{$self->{stack}}).')'  if($self->{stack});  | 
| 
 
 | 
25
 | 
 
 | 
 
 | 
 
 | 
 
 | 
79
 | 
    | 
| 
760
 | 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
203
 | 
     $mess .= " [Validation: $self->{spec}]";  | 
| 
761
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
762
 | 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
83
 | 
     push @{$self->{errors}}, $mess;  | 
| 
 
 | 
73
 | 
 
 | 
 
 | 
 
 | 
 
 | 
202
 | 
    | 
| 
763
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 }  | 
| 
764
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
765
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 q( This release is sponsored by Made In Love: Hand made gifts for your loved ones, friends or even a treat for your own home - http://madeinlove.co.uk );  | 
| 
766
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
    | 
| 
767
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 
 | 
 __END__  |