- Removed use of $Revision$ SVN keyword to generate VERSION variables; now sub-module...
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Producer / TT / Base.pm
CommitLineData
f5f03b78 1package SQL::Translator::Producer::TT::Base;
2
3# -------------------------------------------------------------------
821a0fde 4# $Id$
f5f03b78 5# -------------------------------------------------------------------
478f608d 6# Copyright (C) 2002-2009 SQLFairy Authors
f5f03b78 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
11a8c77a 23=pod
f5f03b78 24
25=head1 NAME
26
11a8c77a 27SQL::Translator::Producer::TT::Base - TT (Template Toolkit) based Producer base
28class.
f5f03b78 29
30=cut
31
f5f03b78 32use strict;
33
478f608d 34use vars qw[ @EXPORT_OK ];
f5f03b78 35
36use Template;
37use Data::Dumper;
bfd86e76 38use IO::Handle;
f5f03b78 39use Exporter;
40use base qw(Exporter);
41@EXPORT_OK = qw(produce);
42
43use 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.
47sub produce {
48 return __PACKAGE__->new( translator => shift )->run;
49};
50
51sub 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
62sub translator { shift->{translator}; }
63sub schema { shift->{translator}->schema(@_); }
64
7f3fc883 65# Util args access method.
f5f03b78 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
7f3fc883 70# exist in the args are returned as undef.
f5f03b78 71sub args {
72 my $me = shift;
73
74 # No args
75 unless (@_) {
7f3fc883 76 return wantarray
f5f03b78 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.
91sub 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;
7f3fc883 99 my $tt = Template->new(
f5f03b78 100 #DEBUG => $me->translator->debug,
7f3fc883 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
f5f03b78 105 ) || die "Failed to initialize Template object: ".Template->error;
106
7f3fc883 107 $tt->process( $tmpl, {
108 $me->tt_default_vars,
109 $me->tt_vars, # Sub-class hook for adding vars
110 }, \$out )
f5f03b78 111 or die "Error processing template '$tmpl': ".$tt->error;
112
113 return $out;
114}
115
11a8c77a 116
117# Sub class hooks
118#-----------------------------------------------------------------------------
119
120sub tt_config { () };
121
bfd86e76 122sub 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};
f5f03b78 138
f5f03b78 139sub tt_default_vars {
140 my $me = shift;
141 return (
142 translator => $me->translator,
bfd86e76 143 schema => $me->pre_process_schema($me->translator->schema),
f5f03b78 144 );
145}
146
bfd86e76 147sub pre_process_schema { $_[1] }
148
7f3fc883 149sub tt_vars { () };
150
f5f03b78 1511;
152
153# -------------------------------------------------------------------
154
155=pod
156
11a8c77a 157=head1 SYNOPSIS
158
466c88de 159 # Create a producer using a template in the __DATA__ section.
11a8c77a 160 package SQL::Translator::Producer::Foo;
161
162 use base qw/SQL::Translator::Producer::TT::Base/;
163
f33f9d70 164 # Convert produce call into a method call on our new class
11a8c77a 165 sub produce { return __PACKAGE__->new( translator => shift )->run; };
166
11a8c77a 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
bfd86e76 173 # Put template in DATA section (or use file with ttfile producer arg)
174 __DATA__
175 Schema
f33f9d70 176
bfd86e76 177 Database: [% schema.database %]
178 Foo: $foo
179 ...
180
11a8c77a 181=head1 DESCRIPTION
182
11a8c77a 183A base class producer designed to be sub-classed to create new TT based
184producers cheaply - by simply giving the template to use and sprinkling in some
185extra template variables and config.
186
466c88de 187You can find an introduction to this module in L<SQL::Translator::Manual>.
188
11a8c77a 189The 1st thing the module does is convert the produce sub routine call we get
f33f9d70 190from SQL::Translator into a method call on an object, which we can then
191sub-class. This is done with the following code which needs to appear in B<all>
192sub classes.
11a8c77a 193
194 # Convert produce call into an object method call
195 sub produce { return __PACKAGE__->new( translator => shift )->run; };
196
197See L<PRODUCER OBJECT> below for details.
198
f33f9d70 199The upshot of this is we can make new template producers by sub classing this
200base class, adding the above snippet and a template.
201The module also provides a number of hooks into the templating process,
202see L<SUB CLASS HOOKS> for details.
11a8c77a 203
204See the L<SYNOPSIS> above for an example of creating a simple producer using
205a single template stored in the producers DATA section.
206
207=head1 SUB CLASS HOOKS
208
f33f9d70 209Sub-classes can override these methods to control the templating by giving
11a8c77a 210the template source, adding variables and giving config to the Tempate object.
211
212=head2 tt_config
213
214 sub tt_config { ( INTERPOLATE => 1 ); }
215
f33f9d70 216Return hash of Template config to add to that given to the L<Template> C<new>
217method.
11a8c77a 218
219=head2 tt_schema
220
221 sub tt_schema { "foo.tt"; }
222 sub tt_schema { local $/ = undef; \<DATA>; }
223
f33f9d70 224The template to use, return a file name or a scalar ref of TT
225source, or an L<IO::Handle>. See L<Template> for details, as the return from
226this is passed on to it's C<produce> method.
11a8c77a 227
228The default implimentation uses the producer arg C<ttfile> as a filename to read
f33f9d70 229the template from. If the arg isn't there it will look for a C<__DATA__> section
bfd86e76 230in the class, reading it as template source if found. Returns undef if both
231these fail, causing the produce call to fail with a 'no template!' error.
11a8c77a 232
233=head2 tt_vars
234
235 sub tt_vars { ( foo => "bar" ); }
236
f33f9d70 237Return hash of template vars to use in the template. Nothing added here
11a8c77a 238by default, but see L<tt_default_vars> for the variables you get for free.
239
240=head2 tt_default_vars
241
242Return a hash-ref of the default vars given to the template.
243You wouldn't normally over-ride this, just inherit the default implimentation,
244to get the C<translator> & C<schema> variables, then over-ride L<tt_vars> to add
245your own.
246
247The current default variables are:
248
249=over 4
250
251=item schema
252
253The schema to template.
254
255=item translator
256
257The L<SQL::Translator> object.
258
259=back
260
bfd86e76 261=head2 pre_process_schema
262
263WARNING: This method is Experimental so may change!
264
f33f9d70 265Called with the L<SQL::Translator::Schema> object and should return one (it
266doesn't have to be the same one) that will become the C<schema> varibale used
267in the template.
bfd86e76 268
269Gets called from tt_default_vars.
270
11a8c77a 271=head1 PRODUCER OBJECT
272
273The rest of the methods in the class set up a sub-classable producer object.
274You normally just inherit them.
275
276=head2 new
277
278 my $tt_producer = TT::Base->new( translator => $translator );
279
280Construct a new TT Producer object. Takes a single, named arg of the
281L<SQL::Translator> object running the translation. Dies if this is not given.
282
283=head2 translator
284
285Return the L<SQL::Translator> object.
286
287=head2 schema
288
289Return the L<SQL::Translator::Schema> we are translating. This is equivilent
290to C<< $tt_producer->translator->schema >>.
291
f33f9d70 292=head2 run
293
294Called to actually produce the output, calling the sub class hooks. Returns the
295produced text.
296
11a8c77a 297=head2 args
298
299Util wrapper method around C<< TT::Base->translator->producer_args >> for
300(mostley) readonly access to the producer args. How it works depends on the
301number 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.
f33f9d70 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.
11a8c77a 308
f33f9d70 309This is still a bit messy but is a handy way to access the producer args when
310you use your own to drive the templating.
11a8c77a 311
f33f9d70 312=head1 SEE ALSO
f5f03b78 313
f33f9d70 314L<perl>,
315L<SQL::Translator>,
316L<Template>.
f5f03b78 317
318=head1 TODO
319
11a8c77a 320- Add support for a sqlf template repository, set as an INCLUDE_PATH,
321so that sub-classes can easily include file based templates using relative
322paths.
f5f03b78 323
f33f9d70 324- Pass in template vars from the producer args and command line.
325
f5f03b78 326- Merge in TT::Table.
327
11a8c77a 328- Hooks to pre-process the schema and post-process the output.
329
f33f9d70 330=head1 AUTHOR
f5f03b78 331
f33f9d70 332Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.
f5f03b78 333
334=cut