Documentation.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Producer / TT / Base.pm
CommitLineData
f5f03b78 1package SQL::Translator::Producer::TT::Base;
2
3# -------------------------------------------------------------------
11a8c77a 4# $Id: Base.pm,v 1.3 2004-05-14 00:46:32 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 ];
11a8c77a 35$VERSION = sprintf "%d.%02d", q$Revision: 1.3 $ =~ /(\d+)\.(\d+)/;
f5f03b78 36
37use Template;
38use Data::Dumper;
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
f5f03b78 122sub tt_schema { shift->args("ttfile") };
123
f5f03b78 124sub tt_default_vars {
125 my $me = shift;
126 return (
127 translator => $me->translator,
128 schema => $me->translator->schema,
129 );
130}
131
7f3fc883 132sub tt_vars { () };
133
f5f03b78 1341;
135
136# -------------------------------------------------------------------
137
138=pod
139
11a8c77a 140=head1 SYNOPSIS
141
142 package SQL::Translator::Producer::Foo;
143
144 use base qw/SQL::Translator::Producer::TT::Base/;
145
146 # Convert produce call into an object of our new class
147 sub produce { return __PACKAGE__->new( translator => shift )->run; };
148
149 # Return file name or template source
150 sub tt_schema { local $/ = undef; \<DATA>; }
151
152 # Configure the Template object.
153 sub tt_config { ( INTERPOLATE => 1 ); }
154
155 # Extra vars to add to the template
156 sub tt_vars { ( foo => "bar" ); }
157
158=head1 DESCRIPTION
159
160WARNING: This is currently WORK IN PROGRESS and so subject to change,
161but it does work ;-)
162
163A base class producer designed to be sub-classed to create new TT based
164producers cheaply - by simply giving the template to use and sprinkling in some
165extra template variables and config.
166
167The 1st thing the module does is convert the produce sub routine call we get
168from SQL::Translator into a method call on an object, so we can sub-class it.
169This is done with the following code which B<must> appear in B<all> sub
170classes.
171
172 # Convert produce call into an object method call
173 sub produce { return __PACKAGE__->new( translator => shift )->run; };
174
175See L<PRODUCER OBJECT> below for details.
176
177The upshot of this is we can make new template producers by writing a template,
178then creating a module that starts like this;
179
180 package SQL::Translator::Producer::Foo;
181
182 use base qw/SQL::Translator::Producer::TT::Base/;
183
184 # Convert produce call into an object of our new class
185 sub produce { return __PACKAGE__->new( translator => shift )->run; };
186
187And then over ride the hooks detailed below in L<SUB CLASS HOOKS>.
188
189See the L<SYNOPSIS> above for an example of creating a simple producer using
190a single template stored in the producers DATA section.
191
192=head1 SUB CLASS HOOKS
193
194Sub-classes should override these methods to control the templating by giving
195the template source, adding variables and giving config to the Tempate object.
196
197=head2 tt_config
198
199 sub tt_config { ( INTERPOLATE => 1 ); }
200
201Return hash of Template config to add to the config given to the
202C<< Template->new >> method.
203
204=head2 tt_schema
205
206 sub tt_schema { "foo.tt"; }
207 sub tt_schema { local $/ = undef; \<DATA>; }
208
209Should return a template file name to use, or a scalar ref of TT source, or
210an L<IO::Handle>. See L<Template> for details, as the return from this is passed
211on to the produce call.
212
213The default implimentation uses the producer arg C<ttfile> as a filename to read
214the template from.
215
216=head2 tt_vars
217
218 sub tt_vars { ( foo => "bar" ); }
219
220Return hash of template vars to use in the template. Doesn't add anything
221by default, but see L<tt_default_vars> for the variables you get for free.
222
223=head2 tt_default_vars
224
225Return a hash-ref of the default vars given to the template.
226You wouldn't normally over-ride this, just inherit the default implimentation,
227to get the C<translator> & C<schema> variables, then over-ride L<tt_vars> to add
228your own.
229
230The current default variables are:
231
232=over 4
233
234=item schema
235
236The schema to template.
237
238=item translator
239
240The L<SQL::Translator> object.
241
242=back
243
244=head1 PRODUCER OBJECT
245
246The rest of the methods in the class set up a sub-classable producer object.
247You normally just inherit them.
248
249=head2 new
250
251 my $tt_producer = TT::Base->new( translator => $translator );
252
253Construct a new TT Producer object. Takes a single, named arg of the
254L<SQL::Translator> object running the translation. Dies if this is not given.
255
256=head2 translator
257
258Return the L<SQL::Translator> object.
259
260=head2 schema
261
262Return the L<SQL::Translator::Schema> we are translating. This is equivilent
263to C<< $tt_producer->translator->schema >>.
264
265=head2 args
266
267Util wrapper method around C<< TT::Base->translator->producer_args >> for
268(mostley) readonly access to the producer args. How it works depends on the
269number of arguments you give it and the context.
270
271 No args - Return hashref (the actual hash in Translator) or hash of args.
272 1 arg - Return value of the arg with the passed name.
273 2+ args - List of names. In list context returns values of the given arg names,
274 returns as a hashref in scalar context. Any names given that don't
275 exist in the args are returned as undef.
276
277This is still experimental but is a handy way to access the args when you use
278your own producer args to drive the templating.
279
280=head2 run
281
282Called to actually produce the output, calling the sub class hooks. Returns the
283produced text.
284
f5f03b78 285=head1 AUTHOR
286
287Mark Addison E<lt>grommit@users.sourceforge.netE<gt>.
288
289=head1 TODO
290
11a8c77a 291- Add support for a sqlf template repository, set as an INCLUDE_PATH,
292so that sub-classes can easily include file based templates using relative
293paths.
f5f03b78 294
295- Merge in TT::Table.
296
11a8c77a 297- Hooks to pre-process the schema and post-process the output.
298
f5f03b78 299=head1 SEE ALSO
300
301SQL::Translator.
302
303=cut