File Coverage

blib/lib/Config/Maker/Schema.pm
Criterion Covered Total %
statement 44 45 97.7
branch 2 2 100.0
condition n/a
subroutine 12 12 100.0
pod 0 4 0.0
total 58 63 92.0


line stmt bran cond sub pod time code
1             package Config::Maker::Schema;
2              
3 9     9   62 use utf8;
  9         21  
  9         78  
4 9     9   281 use warnings;
  9         21  
  9         265  
5 9     9   53 use strict;
  9         23  
  9         314  
6              
7 9     9   53 use Carp;
  9         25  
  9         1614  
8              
9 9     9   136 use Config::Maker;
  9         25  
  9         632  
10 9     9   74 use Config::Maker::Type;
  9         22  
  9         9740  
11              
12             sub type {
13 105     105 0 664 Config::Maker::Type->new(@_);
14             }
15              
16             # Top-level element "schema"
17              
18             my $schema = type(
19             name => 'schema',
20             format => ['anon_group'],
21             contexts => [any => '/', any => '*'],
22             actions => [\&process_schema],
23             );
24              
25             # Global 'type' element
26              
27             my $type = type(
28             name => 'type',
29             format => [named_group => ['identifier']],
30             contexts => [any => $schema],
31             actions => [\&process_type],
32             );
33              
34             # Local 'type' element and 'contains' element
35              
36             my $itype = type(
37             name => 'type',
38             format => [named_group => [pair => ['identifier'], ['identifier']]],
39             contexts => [any => $type],
40             actions => [\&process_itype],
41             );
42             $itype->add(any => $itype);
43              
44             my $contains = type(
45             name => 'contains',
46             format => [simple => [pair => ['identifier'], ['identifier']]],
47             contexts => [any => $type, any => $itype],
48             );
49              
50             # Format elements
51              
52             my $simple = type(
53             name => 'simple',
54             format => [simple => [nested_list => 'string']],
55             contexts => [opt => $type, opt => $itype],
56             );
57              
58             my $anon_group = type(
59             name => 'anon_group',
60             format => [simple => ['void']],
61             contexts => [opt => $type, opt => $itype],
62             );
63              
64             my $named_group = type(
65             name => 'named_group',
66             format => [simple => [nested_list => 'string']],
67             contexts => [opt => $type, opt => $itype],
68             );
69             $type->addchecks(one => 'simple|anon_group|named_group');
70             $itype->addchecks(one => 'simple|anon_group|named_group');
71              
72             # "toplevel" modifier
73             my $top_level = type(
74             name => 'toplevel',
75             format => [simple => ['void']],
76             contexts => [opt => $type, opt => $itype],
77             );
78              
79             # Action elements
80              
81             my $action = type(
82             name => 'action',
83             format => [simple => ['perlcode']],
84             contexts => [any => $type, any => $itype],
85             );
86              
87             # Processing schema. Ugh!
88              
89             sub _get_format {
90 24     24   136 my ($fmt) = $_->get1('simple|anon_group|named_group');
91 24         99 [ "$fmt->{-type}", $fmt->{-value} ];
92             }
93              
94             sub _do_type {
95 24     24   224 $_{format} = _get_format();
96 11         78 $_{children} = [ map {
97 24         144 $_->{-value}->[0], $_->{-data}
98             } $_->get('type') ];
99 24 100       106 push @{$_{contexts}}, any => '/' if $_->get('toplevel');
  11         194  
100 0         0 $_{actions} = [ map {
101 24         103 Config::Maker::exe("sub $_->{-value}");
102             } $_->get('action') ];
103 24         124 $_->{-data} = type(\%_);
104             }
105              
106             sub process_itype
107             {
108 11     11 0 33 local ($_) = @_;
109 11         27 local %_;
110 11         89 $_{name} = $_[0]->{-value}->[1];
111 11         35 $_{contexts} = [];
112 11         38 &_do_type;
113             }
114              
115             sub process_type
116             {
117 13     13 0 38 local ($_) = @_;
118 13         29 local %_;
119 13         84 $_{name} = $_[0]->{-value};
120 13         83 $_{contexts} = [any => '*'],
121             &_do_type;
122             }
123              
124             sub process_schema
125             {
126 6     6 0 25 local ($_) = @_;
127             # Types are already processed!
128             # But now we need to process cross-refs...
129 6         37 for my $type ($_->get('**/type')) {
130 24         167 DBG "Type $type->{-data}...";
131 24         126 for my $cont ($type->get('contains')) {
132 5         72 DBG "Contains $cont->{-value}[0] $cont->{-value}[1]";
133 5         14 $type->{-data}->add(@{$cont->{-value}})
  5         32  
134             }
135             }
136             }
137              
138             1;
139              
140             __END__