File Coverage

blib/lib/WSST/Generator.pm
Criterion Covered Total %
statement 36 156 23.0
branch 3 44 6.8
condition 4 13 30.7
subroutine 10 13 76.9
pod 3 3 100.0
total 56 229 24.4


line stmt bran cond sub pod time code
1             package WSST::Generator;
2              
3 1     1   39338 use strict;
  1         2  
  1         33  
4 1     1   5 use base qw(WSST::Generator);
  1         3  
  1         165  
5 1     1   5 use File::Find qw(find);
  1         1  
  1         86  
6 1     1   5 use File::Basename qw(dirname);
  1         1  
  1         108  
7 1     1   5 use File::Path qw(mkpath);
  1         1  
  1         55  
8 1     1   405 use WSST::Schema;
  1         3  
  1         27  
9 1     1   459 use WSST::CodeTemplate;
  1         5  
  1         674  
10              
11             our $VERSION = '0.1.1';
12              
13             my $TMPL_PACKAGE_ID = 0;
14              
15             sub new {
16 1     1 1 15 my $class = shift;
17 1         4 my $self = {@_};
18 1   33     5 $self->{tmpl_dir} ||= _find_tmpl_dir();
19 1         4 return bless($self, $class);
20             }
21              
22             sub generator_names {
23 1     1 1 1306 my $self = shift;
24            
25 1         46 my $names = [];
26            
27 1 50       72 opendir(DIR, $self->{tmpl_dir})
28             || die "failed opendir('$self->{tmpl_dir}'): $!";
29 1         24 while (my $ent = readdir(DIR)) {
30 5 100 100     85 next if $ent =~ /^\./ || ! -d "$self->{tmpl_dir}/$ent";
31 2         10 push(@$names, $ent);
32             }
33 1         18 closedir(DIR);
34            
35 1         17 return [sort @$names];
36             }
37              
38             sub generate {
39 0     0 1   my $self = shift;
40 0           my $name = shift;
41 0           my $schema = shift;
42 0   0       my $opts = shift || {};
43              
44 0           my $result = [];
45            
46 0           my $vars = $schema->clone_data;
47 0           foreach my $opt_var (@{$opts->{var}}) {
  0            
48 0           my ($key, $val) = split(/=/, $opt_var, 2);
49 0           $vars->{$key} = $val;
50             }
51            
52 0           my $tmpl_dir = "$self->{tmpl_dir}/$name";
53 0           my $tmpl = new WSST::CodeTemplate(tmpl_dirs => [$tmpl_dir],
54             vars => $vars);
55            
56 0   0       my $odir = ($opts->{outdir} || "output") . "/$name";
57 0 0         unless (-d $odir) {
58 0 0         mkdir($odir) || die "failed mkdir('$odir'): $!";
59             }
60              
61 0           my $files = [];
62 0           my $libs = [];
63             my $wanted = sub {
64 0 0 0 0     push(@$files, $File::Find::name) if /\.tmpl$/ && !/^inc_/;
65 0 0         push(@$libs, $File::Find::name) if /\.pm$/;
66 0           };
67 0           find($wanted, $tmpl_dir);
68            
69 0 0         return [] unless @$files;
70            
71 0           foreach my $method (@{$tmpl->get('methods')}) {
  0            
72 0           $method->{class_name} = ucfirst($method->{name});
73 0           $method->{class_name} =~ s/_(.)/uc($1)/eg;
  0            
74 0           $method->{interface_name} = $method->{name};
75             }
76            
77 0           my $listeners = {};
78              
79 0           my $tmpl_pkg = undef;
80 0 0         if (@$libs) {
81 0           my $tmpl_pkg_name = "TMPL" . $TMPL_PACKAGE_ID++;
82 0           $tmpl_pkg = "WSST::Generator::$tmpl_pkg_name";
83             {
84 1     1   11 no strict 'refs';
  1         8  
  1         1206  
  0            
85 0           *{"${tmpl_pkg}::schema"} = \$schema;
  0            
86 0           *{"${tmpl_pkg}::opts"} = \$opts;
  0            
87 0           *{"${tmpl_pkg}::tmpl"} = \$tmpl;
  0            
88 0           *{"${tmpl_pkg}::files"} = \$files;
  0            
89 0           *{"${tmpl_pkg}::libs"} = \$libs;
  0            
90 0           *{"${tmpl_pkg}::result"} = \$result;
  0            
91 0           *{"${tmpl_pkg}::tmpl_dir"} = \$tmpl_dir;
  0            
92 0           *{"${tmpl_pkg}::odir"} = \$odir;
  0            
93 0           *{"${tmpl_pkg}::listeners"} = \$listeners;
  0            
94             }
95 0           foreach my $lib (@$libs) {
96 0           eval qq{
97             package ${tmpl_pkg};
98             require '$lib';
99             };
100 0 0         if ($@) {
101 0           warn __PACKAGE__ . ": library load error: $@\n";
102             }
103             }
104 0           my $hash = \%{$WSST::Generator::{"${tmpl_pkg_name}::"}};
  0            
105 0           foreach my $key (keys %$hash) {
106 0 0         next if $tmpl->get($key);
107             #$tmpl->set($key => $hash->{$key});
108 0           $tmpl->set($key => \&{$hash->{$key}});
  0            
109             }
110             }
111            
112 0           foreach my $file (@$files) {
113 0           my $ofile = $file;
114 0           $ofile =~ s/^\Q$tmpl_dir\E//;
115 0           $ofile =~ s/\.tmpl$//;
116            
117 0           my $fdir = dirname($file);
118 0           unshift(@{$tmpl->{tmpl_dirs}}, $fdir);
  0            
119 0 0         if ($file =~ /{method\.([a-zA-Z_][a-zA-Z0-9_]*)}/) {
120 0           foreach my $method (@{$tmpl->get('methods')}) {
  0            
121 0           my $ofile2 = $ofile;
122 0 0         $ofile2 =~ s/{method\.([a-zA-Z_][a-zA-Z0-9_]*)}/$method->{$1}||"{$1}"/eg;
  0            
123 0           $ofile2 =~ s/{([a-zA-Z_][a-zA-Z0-9_]*)}/
124 0           my $val = $tmpl->get($1);
125 0 0         $val = &{$val}() if (ref $val eq 'CODE');
  0            
126 0           $val;
127             /egx;
128 0 0         die $@ if $@;
129 0           $ofile2 = $odir . $ofile2;
130            
131 0           $tmpl->set('method' => $method);
132            
133 0           my $tmpl_name = $file;
134 0           $tmpl_name =~ s#^\Q$tmpl_dir/\E##;
135 0           my $odata = $tmpl->expand($tmpl_name);
136            
137 0           my $osubdir = dirname($ofile2);
138 0 0         unless (-d $osubdir) {
139 0 0         mkpath($osubdir)
140             || die "failed mkpath('$osubdir'): $!";
141             }
142            
143 0 0         open(OUT, ">$ofile2")
144             || die "failed open('>$ofile2'): $!";
145 0           print OUT $odata;
146 0           close(OUT);
147              
148 0           push(@$result, $ofile2);
149             }
150             } else {
151 0           $ofile =~ s/{([a-zA-Z_][a-zA-Z0-9_]*)}/
152 0           my $val = $tmpl->get($1);
153 0 0         $val = &{$val}() if (ref $val eq 'CODE');
  0            
154 0           $val;
155             /egx;
156 0           $ofile = $odir . $ofile;
157              
158 0           my $tmpl_name = $file;
159 0           $tmpl_name =~ s#^\Q$tmpl_dir/\E##;
160 0           my $odata = $tmpl->expand($tmpl_name);
161            
162 0           my $osubdir = dirname($ofile);
163 0 0         unless (-d $osubdir) {
164 0 0         mkpath($osubdir)
165             || die "failed mkpath('$osubdir'): $!";
166             }
167            
168 0 0         open(OUT, ">$ofile")
169             || die "failed open('>$ofile'): $!";
170 0           print OUT $odata;
171 0           close(OUT);
172            
173 0           push(@$result, $ofile);
174             }
175 0           shift(@{$tmpl->{tmpl_dirs}});
  0            
176             }
177            
178 0           foreach my $func (@{$listeners->{post_generate}}) {
  0            
179 0           &{$func}();
  0            
180             }
181            
182 0           return $result;
183             }
184              
185             sub _find_tmpl_dir {
186 0     0     foreach my $base_dir (@INC) {
187 0           my $dir = "$base_dir/WSST/Templates";
188 0 0         return $dir if -d $dir;
189             }
190 0           return undef;
191             }
192              
193             =head1 NAME
194              
195             WSST::Generator - Generator class of WSST
196              
197             =head1 DESCRIPTION
198              
199             Generator is a template base generator.
200             The generate method of this class looks for
201             the template file from the template directory,
202             and processes those files.
203              
204             =head1 METHODS
205              
206             =head2 new
207              
208             Constructor.
209              
210             =head2 generator_names
211              
212             Returns generator name and alias.
213             This method returns subdirectory name of template directory.
214              
215             If the structure of template directory is as follows,
216             ["perl", "php"] is returned.
217              
218             templates/
219             |-- perl/
220             | `-- ...
221             `-- php/
222             `-- ...
223              
224             =head2 generate
225              
226             Generate library and return generated file names
227             by processing template files in template directory.
228              
229             =head1 SEE ALSO
230              
231             http://code.google.com/p/wsst/
232              
233             =head1 AUTHORS
234              
235             Mitsuhisa Oshikawa
236             Yusuke Kawasaki
237              
238             =head1 COPYRIGHT AND LICENSE
239              
240             Copyright 2008 WSS Project Team
241              
242             =cut
243             1;