Strip evil svn:keywords
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Producer / TT / Base.pm
1 package SQL::Translator::Producer::TT::Base;
2
3 # -------------------------------------------------------------------
4 # $Id: Base.pm 1440 2009-01-17 16:31:57Z jawnsy $
5 # -------------------------------------------------------------------
6 # Copyright (C) 2002-2009 SQLFairy Authors
7 #
8 # This program is free software; you can redistribute it and/or
9 # modify it under the terms of the GNU General Public License as
10 # published by the Free Software Foundation; version 2.
11 #
12 # This program is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 # General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 # 02111-1307  USA
21 # -------------------------------------------------------------------
22
23 =pod
24
25 =head1 NAME
26
27 SQL::Translator::Producer::TT::Base - TT (Template Toolkit) based Producer base
28 class.
29
30 =cut
31
32 use strict;
33
34 use vars qw[ @EXPORT_OK ];
35
36 use Template;
37 use Data::Dumper;
38 use IO::Handle;
39 use Exporter;
40 use base qw(Exporter);
41 @EXPORT_OK = qw(produce);
42
43 use SQL::Translator::Utils 'debug';
44
45 # Hack to convert the produce call into an object. ALL sub-classes need todo
46 # this so that the correct class gets created.
47 sub produce {
48     return __PACKAGE__->new( translator => shift )->run;
49 };
50
51 sub new {
52     my $proto = shift;
53     my $class = ref $proto || $proto;
54     my %args  = @_;
55
56     my $me = bless {}, $class;
57     $me->{translator} = delete $args{translator} || die "Need a translator.";
58
59     return $me;
60 }
61
62 sub translator { shift->{translator}; }
63 sub schema     { shift->{translator}->schema(@_); }
64
65 # Util args access method.
66 # No args - Return hashref (the actual hash in Translator) or hash of args.
67 # 1 arg   - Return that named args value.
68 # Args    - List of names. Return values of the given arg names in list context
69 #           or return as hashref in scalar context. Any names given that don't
70 #           exist in the args are returned as undef.
71 sub args {
72     my $me = shift;
73
74     # No args
75     unless (@_) {
76         return wantarray
77             ? %{ $me->{translator}->producer_args }
78             : $me->{translator}->producer_args
79         ;
80     }
81
82     # 1 arg. Return the value whatever the context.
83     return $me->{translator}->producer_args->{$_[0]} if @_ == 1;
84
85     # More args so return values list or hash ref
86     my %args = %{ $me->{translator}->producer_args };
87     return wantarray ? @args{@_} : { map { ($_=>$args{$_}) } @_ };
88 }
89
90 # Run the produce and return the result.
91 sub run {
92     my $me = shift;
93     my $scma = $me->schema;
94     my %args = %{$me->args};
95     my $tmpl = $me->tt_schema or die "No template!";
96
97     debug "Processing template $tmpl\n";
98     my $out;
99     my $tt = Template->new(
100         #DEBUG    => $me->translator->debug,
101         ABSOLUTE => 1,  # Set so we can use from the command line sensibly
102         RELATIVE => 1,  # Maybe the cmd line code should set it! Security!
103         $me->tt_config, # Hook for sub-classes to add config
104         %args,          # Allow any TT opts to be passed in the producer_args
105     ) || die "Failed to initialize Template object: ".Template->error;
106
107     $tt->process( $tmpl, {
108         $me->tt_default_vars,
109         $me->tt_vars,          # Sub-class hook for adding vars
110     }, \$out )
111     or die "Error processing template '$tmpl': ".$tt->error;
112
113     return $out;
114 }
115
116
117 # Sub class hooks
118 #-----------------------------------------------------------------------------
119
120 sub tt_config { () };
121
122 sub tt_schema {
123     my $me = shift;
124     my $class = ref $me;
125
126     my $file = $me->args("ttfile");
127     return $file if $file;
128
129     no strict 'refs';
130     my $ref = *{"$class\:\:DATA"}{IO};
131     if ( $ref->opened ) {
132         local $/ = undef; # Slurp mode
133         return \<$ref>;
134     }
135
136     undef;
137 };
138
139 sub tt_default_vars {
140     my $me = shift;
141     return (
142         translator => $me->translator,
143         schema     => $me->pre_process_schema($me->translator->schema),
144     );
145 }
146
147 sub pre_process_schema { $_[1] }
148
149 sub tt_vars   { () };
150
151 1;
152
153 # -------------------------------------------------------------------
154
155 =pod
156
157 =head1 SYNOPSIS
158
159  # Create a producer using a template in the __DATA__ section.
160  package SQL::Translator::Producer::Foo;
161
162  use base qw/SQL::Translator::Producer::TT::Base/;
163
164  # Convert produce call into a method call on our new class
165  sub produce { return __PACKAGE__->new( translator => shift )->run; };
166
167  # Configure the Template object.
168  sub tt_config { ( INTERPOLATE => 1 ); }
169
170  # Extra vars to add to the template
171  sub tt_vars { ( foo => "bar" ); }
172
173  # Put template in DATA section (or use file with ttfile producer arg)
174  __DATA__
175  Schema
176
177  Database: [% schema.database %]
178  Foo: $foo
179  ...
180
181 =head1 DESCRIPTION
182
183 A base class producer designed to be sub-classed to create new TT based
184 producers cheaply - by simply giving the template to use and sprinkling in some
185 extra template variables and config.
186
187 You can find an introduction to this module in L<SQL::Translator::Manual>.
188
189 The 1st thing the module does is convert the produce sub routine call we get
190 from SQL::Translator into a method call on an object, which we can then
191 sub-class. This is done with the following code which needs to appear in B<all>
192 sub classes.
193
194  # Convert produce call into an object method call
195  sub produce { return __PACKAGE__->new( translator => shift )->run; };
196
197 See L<PRODUCER OBJECT> below for details.
198
199 The upshot of this is we can make new template producers by sub classing this
200 base class, adding the above snippet and a template.
201 The module also provides a number of hooks into the templating process,
202 see L<SUB CLASS HOOKS> for details.
203
204 See the L<SYNOPSIS> above for an example of creating a simple producer using
205 a single template stored in the producers DATA section.
206
207 =head1 SUB CLASS HOOKS
208
209 Sub-classes can override these methods to control the templating by giving
210 the template source, adding variables and giving config to the Tempate object.
211
212 =head2 tt_config
213
214  sub tt_config { ( INTERPOLATE => 1 ); }
215
216 Return hash of Template config to add to that given to the L<Template> C<new>
217 method.
218
219 =head2 tt_schema
220
221  sub tt_schema { "foo.tt"; }
222  sub tt_schema { local $/ = undef; \<DATA>; }
223
224 The template to use, return a file name or a scalar ref of TT
225 source, or an L<IO::Handle>. See L<Template> for details, as the return from
226 this is passed on to it's C<produce> method.
227
228 The default implimentation uses the producer arg C<ttfile> as a filename to read
229 the template from. If the arg isn't there it will look for a C<__DATA__> section
230 in the class, reading it as template source if found. Returns undef if both
231 these fail, causing the produce call to fail with a 'no template!' error.
232
233 =head2 tt_vars
234
235  sub tt_vars { ( foo => "bar" ); }
236
237 Return hash of template vars to use in the template. Nothing added here
238 by default, but see L<tt_default_vars> for the variables you get for free.
239
240 =head2 tt_default_vars
241
242 Return a hash-ref of the default vars given to the template.
243 You wouldn't normally over-ride this, just inherit the default implimentation,
244 to get the C<translator> & C<schema> variables, then over-ride L<tt_vars> to add
245 your own.
246
247 The current default variables are:
248
249 =over 4
250
251 =item schema
252
253 The schema to template.
254
255 =item translator
256
257 The L<SQL::Translator> object.
258
259 =back
260
261 =head2 pre_process_schema
262
263 WARNING: This method is Experimental so may change!
264
265 Called with the L<SQL::Translator::Schema> object and should return one (it
266 doesn't have to be the same one) that will become the C<schema> varibale used 
267 in the template.
268
269 Gets called from tt_default_vars.
270
271 =head1 PRODUCER OBJECT
272
273 The rest of the methods in the class set up a sub-classable producer object.
274 You normally just inherit them.
275
276 =head2 new
277
278  my $tt_producer = TT::Base->new( translator => $translator );
279
280 Construct a new TT Producer object. Takes a single, named arg of the
281 L<SQL::Translator> object running the translation. Dies if this is not given.
282
283 =head2 translator
284
285 Return the L<SQL::Translator> object.
286
287 =head2 schema
288
289 Return the L<SQL::Translator::Schema> we are translating. This is equivilent
290 to C<< $tt_producer->translator->schema >>.
291
292 =head2 run
293
294 Called to actually produce the output, calling the sub class hooks. Returns the
295 produced text.
296
297 =head2 args
298
299 Util wrapper method around C<< TT::Base->translator->producer_args >> for
300 (mostley) readonly access to the producer args. How it works depends on the
301 number of arguments you give it and the context.
302
303  No args - Return hashref (the actual hash in Translator) or hash of args.
304  1 arg   - Return value of the arg with the passed name.
305  2+ args - List of names. In list context returns values of the given arg
306            names, returns as a hashref in scalar context. Any names given
307            that don't exist in the args are returned as undef.
308
309 This is still a bit messy but is a handy way to access the producer args when
310 you use your own to drive the templating.
311
312 =head1 SEE ALSO
313
314 L<perl>,
315 L<SQL::Translator>,
316 L<Template>.
317
318 =head1 TODO
319
320 - Add support for a sqlf template repository, set as an INCLUDE_PATH,
321 so that sub-classes can easily include file based templates using relative
322 paths.
323
324 - Pass in template vars from the producer args and command line.
325
326 - Merge in TT::Table.
327
328 - Hooks to pre-process the schema and post-process the output.
329
330 =head1 AUTHOR
331
332 Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.
333
334 =cut