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