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