Commit | Line | Data |
69c7a62f |
1 | package Turnkey::Package; |
2 | |
3 | use strict; |
4 | use Class::MakeMethods::Template::Hash ( |
5 | new => [ 'new' ], |
c8515c9f |
6 | 'array' => [ qw( many ) ], |
7 | hash_of_arrays => [ qw( one2one one2many many2one many2many) ], |
69c7a62f |
8 | scalar => [ qw( base name order primary_key primary_key_accessor table) ], |
9 | ); |
10 | |
11 | |
12 | # get_set => [ qw(order base name table primary_key primary_key_accessor) ], |
13 | # new_with_init => 'new', |
14 | #; |
15 | |
16 | sub init { |
17 | } |
18 | |
19 | 1; |
20 | |
c00bb9f8 |
21 | package SQL::Translator::Producer::Turnkey; |
22 | |
23 | # ------------------------------------------------------------------- |
b75fe3e7 |
24 | # $Id: Turnkey.pm,v 1.4 2003-08-29 08:25:31 allenday Exp $ |
c00bb9f8 |
25 | # ------------------------------------------------------------------- |
26 | # Copyright (C) 2003 Allen Day <allenday@ucla.edu>, |
69c7a62f |
27 | # Brian O'Connor <boconnor@ucla.edu>, |
c00bb9f8 |
28 | # Ying Zhang <zyolive@yahoo.com> |
29 | # |
30 | # This program is free software; you can redistribute it and/or |
31 | # modify it under the terms of the GNU General Public License as |
32 | # published by the Free Software Foundation; version 2. |
33 | # |
34 | # This program is distributed in the hope that it will be useful, but |
35 | # WITHOUT ANY WARRANTY; without even the implied warranty of |
36 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
37 | # General Public License for more details. |
38 | # |
39 | # You should have received a copy of the GNU General Public License |
40 | # along with this program; if not, write to the Free Software |
41 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
42 | # 02111-1307 USA |
43 | # ------------------------------------------------------------------- |
44 | |
45 | use strict; |
46 | use vars qw[ $VERSION $DEBUG ]; |
b75fe3e7 |
47 | $VERSION = sprintf "%d.%02d", q$Revision: 1.4 $ =~ /(\d+)\.(\d+)/; |
c00bb9f8 |
48 | $DEBUG = 1 unless defined $DEBUG; |
49 | |
50 | use SQL::Translator::Schema::Constants; |
51 | use SQL::Translator::Utils qw(header_comment); |
52 | use Data::Dumper; |
53 | use Template; |
54 | |
55 | my %CDBI_auto_pkgs = ( |
56 | MySQL => 'mysql', |
57 | PostgreSQL => 'Pg', |
58 | Oracle => 'Oracle', |
59 | ); |
60 | |
61 | # ------------------------------------------------------------------- |
62 | sub produce { |
63 | my $t = shift; |
64 | my $create = undef; |
65 | local $DEBUG = $t->debug; |
66 | my $no_comments = $t->no_comments; |
67 | my $schema = $t->schema; |
68 | my $args = $t->producer_args; |
69 | my $db_user = $args->{'db_user'} || ''; |
70 | my $db_pass = $args->{'db_pass'} || ''; |
71 | my $main_pkg_name = $args->{'main_pkg_name'} || |
72 | $t->format_package_name('DBI'); |
73 | my $header = header_comment(__PACKAGE__, "# "); |
74 | my $parser_type = ( split /::/, $t->parser_type )[-1]; |
75 | my $from = $CDBI_auto_pkgs{ $parser_type } || ''; |
76 | my $dsn = $args->{'dsn'} || sprintf( 'dbi:%s:_', |
77 | $CDBI_auto_pkgs{ $parser_type } |
78 | ? $CDBI_auto_pkgs{ $parser_type } : $parser_type |
79 | ); |
80 | my $sep = '# ' . '-' x 67; |
81 | |
82 | # |
83 | # Identify "link tables" (have only PK and FK fields). |
84 | # |
85 | my %linkable; |
86 | my %linktable; |
69c7a62f |
87 | my %packages; |
88 | my $order; |
c00bb9f8 |
89 | |
c8515c9f |
90 | # |
91 | # build package objects |
92 | # |
69c7a62f |
93 | foreach my $table ($schema->get_tables){ |
94 | die __PACKAGE__." table ".$table->name." doesn't have a primary key!" unless $table->primary_key; |
95 | die __PACKAGE__." table ".$table->name." can't have a composite primary key!" if ($table->primary_key->fields)[1]; |
c00bb9f8 |
96 | |
c00bb9f8 |
97 | |
69c7a62f |
98 | my $package = Turnkey::Package->new(); |
b75fe3e7 |
99 | $packages{ $table->name } = $package; |
c00bb9f8 |
100 | |
69c7a62f |
101 | $package->order( ++$order ); |
102 | $package->name( $t->format_package_name($table->name) ); |
103 | $package->base( $main_pkg_name ); |
104 | $package->table( $table ); |
105 | $package->primary_key( ($table->primary_key->fields)[0] ); |
106 | # Primary key may have a differenct accessor method name |
107 | $package->primary_key_accessor( |
108 | defined($t->format_pk_name) ? $t->format_pk_name->( $package->name, $package->primary_key ) |
109 | : undef |
110 | ); |
c8515c9f |
111 | |
112 | foreach my $field ($table->get_fields){ |
113 | next unless $field->is_foreign_key; |
114 | |
115 | $package->push_many( $field->foreign_key_reference->reference_table ); |
116 | } |
69c7a62f |
117 | } |
c00bb9f8 |
118 | |
c8515c9f |
119 | # |
120 | # identify FK relationships |
121 | # |
69c7a62f |
122 | foreach my $maylink ( $schema->get_tables ){ |
123 | foreach my $left ($schema->get_tables){ |
124 | foreach my $right ($schema->get_tables){ |
125 | |
126 | next if $left->name eq $right->name; |
127 | |
c8515c9f |
128 | my $lpackage = $packages{$left->name}; |
129 | my $rpackage = $packages{$right->name}; |
130 | |
c8515c9f |
131 | my($link,$lconstraints,$rconstraints) = @{ $maylink->can_link($left,$right) }; |
b75fe3e7 |
132 | warn $left->name, "\t", $maylink->name, "\t", $right->name if $link ne '0'; |
c8515c9f |
133 | |
134 | #one FK to one FK |
135 | if( $link eq 'one2one'){ |
136 | warn "\tone2one"; |
137 | $lpackage->one2one_push($rpackage->name, [$rpackage, $maylink]); |
138 | $rpackage->one2one_push($lpackage->name, [$lpackage, $maylink]); |
139 | |
140 | #one FK to many FK |
141 | } elsif( $link eq 'one2many'){ |
142 | warn "\tone2many"; |
143 | $lpackage->one2many_push($rpackage->name, [$rpackage, $maylink]); |
144 | $rpackage->many2one_push($lpackage->name, [$lpackage, $maylink]); |
145 | |
146 | #many FK to one FK |
147 | } elsif( $link eq 'many2one'){ |
148 | warn "\tmany2one"; |
149 | $lpackage->many2one_push($rpackage->name, [$rpackage, $maylink]); |
150 | $rpackage->one2many_push($lpackage->name, [$lpackage, $maylink]); |
151 | |
152 | #many FK to many FK |
153 | } elsif( $link eq 'many2many'){ |
154 | warn "\tmany2many"; |
b75fe3e7 |
155 | warn $left->name; |
156 | warn $right->name; |
c8515c9f |
157 | $lpackage->many2many_push($rpackage->name, [$rpackage, $maylink]); |
158 | $rpackage->many2many_push($lpackage->name, [$lpackage, $maylink]); |
159 | |
160 | } else { |
161 | #not linkable |
c00bb9f8 |
162 | } |
163 | } |
69c7a62f |
164 | } |
165 | } |
166 | |
167 | # |
c8515c9f |
168 | # create methods |
69c7a62f |
169 | # |
c8515c9f |
170 | foreach my $package_from (values %packages){ |
171 | next unless $package_from->table->is_data; |
172 | |
69c7a62f |
173 | my %linked; |
c00bb9f8 |
174 | |
c8515c9f |
175 | my %o2o = $package_from->one2one; |
176 | warn Dumper(%o2o); |
177 | my %o2m = $package_from->one2many; |
178 | warn Dumper(%o2m); |
179 | my %m2o = $package_from->many2one; |
180 | warn Dumper(%m2o); |
181 | my %m2m = $package_from->many2many; |
182 | warn Dumper(%m2m); |
183 | |
184 | foreach my $package_to (keys %{ $package_from->one2one }){ |
185 | $package_to = $packages{$package_to}; |
186 | foreach my $bridge ( $package_from->one2one($package_to->name) ){ |
187 | $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( |
188 | $package_from->one2one($package_to->name)->[1]->name, |
189 | $package_to->primary_key |
190 | ).'s' |
191 | : $package_from->one2one($package_to->name)->[1]->name .'_'. |
192 | $package_to->primary_key .'s'; |
193 | } |
194 | } |
69c7a62f |
195 | |
c8515c9f |
196 | foreach my $package_to (keys %{ $package_from->one2many }){ |
197 | $package_to = $packages{$package_to}; |
198 | foreach my $bridge ( $package_from->one2many($package_to->name) ){ |
199 | $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( |
200 | $package_from->one2many($package_to->name)->[1]->name, |
201 | $package_to->primary_key |
202 | ).'s' |
203 | : $package_from->one2many($package_to->name)->[1]->name .'_'. |
204 | $package_to->primary_key .'s'; |
205 | } |
206 | } |
207 | |
208 | foreach my $package_to (keys %{ $package_from->many2one }){ |
209 | $package_to = $packages{$package_to}; |
210 | foreach my $bridge ( $package_from->many2one($package_to->name) ){ |
211 | $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( |
212 | $package_from->many2one($package_to->name)->[1]->name, |
213 | $package_to->primary_key |
214 | ).'s' |
215 | : $package_from->many2one($package_to->name)->[1]->name .'_'. |
216 | $package_to->primary_key .'s'; |
217 | } |
218 | } |
219 | |
220 | foreach my $package_to (keys %{ $package_from->many2many }){ |
221 | $package_to = $packages{$package_to}; |
222 | foreach my $bridge ( $package_from->many2many($package_to->name) ){ |
223 | $bridge->[3] = $t->format_fk_name ? $t->format_fk_name->( |
224 | $package_from->many2many($package_to->name)->[1]->name, |
225 | $package_to->primary_key |
226 | ).'s' |
227 | : $package_from->many2many($package_to->name)->[1]->name .'_'. |
228 | $package_to->primary_key .'s'; |
229 | } |
230 | } |
231 | |
232 | |
233 | |
234 | |
235 | # #if one possible traversal via link table |
236 | # if (scalar(@rk_fields) == 1 and scalar(@lk_fields) == 1) { |
237 | # foreach my $rk_field (@rk_fields) { |
238 | # push @{ $packages{ $package->name }{'has_many'}{$link}{'link_one_one'} }, |
239 | # "sub ".$linkmethodname." { my \$self = shift; ". |
240 | # "return map \$_->". |
241 | # ($schema->get_table($link)->primary_key->fields)[0]. |
242 | # ", \$self->".$linkable{$table_from->name}{$link}->name. |
243 | # "_".$rk_field." }\n\n"; |
244 | # } |
245 | # #NOTE: we need to rethink the link method name, as the cardinality |
246 | # #has shifted on us. |
247 | # } elsif (scalar(@rk_fields) == 1) { |
248 | # foreach my $rk_field (@rk_fields) { |
249 | # # ADD CALLBACK FOR PLURALIZATION MANGLING HERE |
250 | # push @{ $packages{ $package->name }{'has_many'}{ $link }{'link_many_one'} }, |
251 | # "sub " . $linkable{$table_from->name}{$link}->name . |
252 | # "s { my \$self = shift; return \$self->" . |
253 | # $linkable{$table_from->name}{$link}->name . "_" . |
254 | # $rk_field . "(\@_) }\n\n"; |
255 | # } |
256 | # } elsif (scalar(@lk_fields) == 1) { |
257 | # #these will be taken care of on the other end... |
258 | # } else { |
259 | # #many many many. need multiple iterations here, data structure revision |
260 | # #to handle N FK sources. This code has not been tested and likely doesn't |
261 | # #work here |
262 | # foreach my $rk_field (@rk_fields) { |
263 | # # ADD CALLBACK FOR PLURALIZATION MANGLING HERE |
264 | # push @{ $packages{ $package->name }{'has_many'}{ $link }{'link_many_many'} }, |
265 | # "sub " . $linkable{$table_from->name}{$link}->name . "_" . $rk_field . |
266 | # "s { my \$self = shift; return \$self->" . |
267 | # $linkable{$table_from->name}{$link}->name . "_" . |
268 | # $rk_field . "(\@_) }\n\n"; |
269 | # } |
270 | # } |
271 | # } |
272 | |
273 | |
274 | # # |
275 | # # Use foreign keys to set up "has_a/has_many" relationships. |
276 | # # |
277 | # foreach my $field ( $table_from->get_fields ) { |
278 | # if ( $field->is_foreign_key ) { |
279 | # my $table_name = $table_from->name; |
280 | # my $field_name = $field->name; |
281 | # my $fk_method = $t->format_fk_name($table_name, $field_name); |
282 | # my $fk = $field->foreign_key_reference; |
283 | # my $ref_table = $fk->reference_table; |
284 | # my $ref_pkg = $t->format_package_name($ref_table); |
285 | # my $ref_field = ($fk->reference_fields)[0]; |
286 | |
287 | # push @{ $packages{ $package->name }{'has_a'} }, |
288 | # $package->name."->has_a( $field_name => '$ref_pkg');\n". |
289 | # "sub $fk_method { return shift->$field_name }\n\n" |
290 | # ; |
c00bb9f8 |
291 | |
292 | |
c8515c9f |
293 | # # |
294 | # # If this table "has a" to the other, then it follows |
295 | # # that the other table "has many" of this one, right? |
296 | # # |
297 | # # No... there is the possibility of 1-1 cardinality |
298 | |
299 | # #if there weren't M-M relationships via the has_many |
300 | # #being set up here, create nice pluralized method alias |
301 | # #rather for user as alt. to ugly tablename_fieldname name |
302 | # if(! $packages{ $ref_pkg }{ 'has_many' }{ $table_from->name } ){ |
303 | # # ADD CALLBACK FOR PLURALIZATION MANGLING HERE |
304 | # #push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name } }, |
305 | # # "sub $table_name\s {\n return shift->$table_name\_$field_name\n}\n\n"; |
306 | # push @{ $packages{ $ref_pkg }{'has_many'}{ $table_from->name }{'fk_pluralized'} }, |
307 | # { table_name => $table_from->name, field_name => $field_name }; |
308 | |
309 | # #else ugly |
310 | # } else { |
311 | # } |
312 | |
313 | # #push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name } }, |
314 | # # "$ref_pkg->has_many(\n '${table_name}_${field_name}', ". |
315 | # # "'$table_pkg_name' => '$field_name'\n);\n\n"; |
316 | # push @{ $packages{ $ref_pkg }{'has_many'}{ $table_name }{pluralized} }, |
317 | # { ref_pkg => $ref_pkg, table_pkg_name => $package->name, table_name => $table_from->name, field_name => $field_name }; |
318 | # } |
319 | # } |
320 | } |
c00bb9f8 |
321 | |
322 | my %metadata; |
323 | $metadata{"packages"} = \%packages; |
324 | $metadata{"linkable"} = \%linkable; |
325 | return(translateForm($t, \%metadata)); |
326 | } |
327 | |
328 | ########################################### |
329 | # Here documents for the tt2 templates # |
330 | ########################################### |
331 | |
332 | my $turnkey_atom_tt2 = <<'EOF'; |
333 | [% ###### DOCUMENT START ###### %] |
334 | |
335 | [% FOREACH package = linkable %] |
336 | |
337 | ############################################## |
338 | |
339 | package Durian::Atom::[% package.key FILTER ucfirst %]; |
340 | |
341 | [% pname = package.key FILTER ucfirst%] |
342 | [% pkey = "Durian::Model::${pname}" %] |
343 | |
344 | use base qw(Durian::Atom); |
345 | use Data::Dumper; |
346 | |
347 | sub can_render { |
348 | return 1; |
349 | } |
350 | |
351 | sub render { |
352 | my $self = shift; |
353 | my $dbobject = shift; |
354 | # Assumption here that if it's not rendering on it's own dbobject |
355 | # then it's a list. This will be updated when AtomLists are implemented -boconnor |
356 | if(ref($dbobject) eq 'Durian::Model::[% package.key FILTER ucfirst %]') { |
357 | return(_render_record($dbobject)); |
358 | } |
359 | else { return(_render_list($dbobject)); } |
360 | } |
361 | |
362 | sub _render_record { |
363 | my $dbobject = shift; |
364 | my @output = (); |
365 | my $row = {}; |
366 | my $field_hash = {}; |
367 | [% FOREACH field = packages.$pkey.columns_essential %] |
368 | $field_hash->{[% field %]} = $dbobject->[% field %](); |
369 | [% END %] |
370 | $row->{data} = $field_hash; |
371 | $row->{id} = $dbobject->id(); |
372 | push @output, $row; |
373 | return(\@output); |
374 | } |
375 | |
376 | sub _render_list { |
377 | my $dbobject = shift; |
378 | my @output = (); |
379 | my @objects = $dbobject->[% package.key %]s; |
380 | foreach my $object (@objects) |
381 | { |
382 | my $row = {}; |
383 | my $field_hash = {}; |
384 | [% FOREACH field = packages.$pkey.columns_essential %] |
385 | $field_hash->{[% field %]} = $object->[% field %](); |
386 | [% END %] |
387 | $row->{data} = $field_hash; |
388 | $row->{id} = $object->id(); |
389 | push @output, $row; |
390 | } |
391 | return(\@output); |
392 | } |
393 | |
394 | sub head { |
395 | return 1; |
396 | } |
397 | |
398 | 1; |
399 | |
400 | [% END %] |
401 | EOF |
402 | |
403 | my $turnkey_dbi_tt2 = <<EOF; |
404 | [% ####### MACRO START ###### %] |
405 | |
406 | [% MACRO printPackage(package) BLOCK %] |
407 | # -------------------------------------------- |
408 | package [% package.pkg_name %]; |
409 | use base '[% package.base %]'; |
410 | use Class::DBI::Pager; |
411 | |
412 | [% package.pkg_name %]->set_up_table('[% package.table %]'); |
413 | [% package.pkg_name %]->columns(Primary => qw/[% printList(package.columns_primary) %]/); |
414 | [% package.pkg_name %]->columns(Essential => qw/[% printList(package.columns_essential) %]/); |
415 | |
416 | [% printPKAccessors(package.columns_primary, package.table) %] |
417 | [% printHasMany(package.has_many, package.table) %] |
418 | [% printHasA(package.has_a, package.pkg_name) %] |
419 | |
420 | [% END %] |
421 | |
422 | [% MACRO printPKAccessors(array, name) BLOCK %] |
423 | # |
424 | # Primary key accessor |
425 | # |
426 | [% FOREACH item = array %] |
427 | sub [% name %] { |
428 | shift->[% item %]; |
429 | } |
430 | [% END %] |
431 | [% END %] |
432 | |
433 | [% MACRO printHasMany(hash, name) BLOCK %] |
434 | # |
435 | # Has Many |
436 | # |
437 | [% FOREACH group = hash %][% FOREACH item = group.value %][% FOREACH arr = item.value %] |
438 | # Key: [% group.key %] |
439 | # Relationship: [% item.key %] |
440 | [% IF item.key == 'fk_pluralized' %] |
441 | sub [% arr.table_name -%]s { |
442 | return shift->[% arr.table_name %]_[% arr.field_name %] |
443 | }; |
444 | [% ELSIF item.key == 'pluralized' %] |
445 | [% arr.ref_pkg %]->has_many('[% arr.table_name %]_[% arr.field_name %]', '[% arr.table_pkg_name %]' => '[% arr.field_name %]'); |
446 | [% ELSIF item.key == 'link_one_one' %] |
447 | [% FOREACH line = item.value %] |
448 | [% line %] |
449 | [% END %] |
450 | [% ELSIF item.key == 'link_many_one' %] |
451 | [% FOREACH line = item.value %] |
452 | [% line %] |
453 | [% END %] |
454 | [% ELSIF item.key == 'link_many_many' %] |
455 | [% FOREACH line = item.value %] |
456 | [% line %] |
457 | [% END %] |
458 | [% END %] |
459 | |
460 | [% END %][% END %][% END %][% END %] |
461 | |
462 | [% MACRO printHasA(hash, pkg_name) BLOCK %] |
463 | # |
464 | # Has A |
465 | # |
466 | [% #name %] |
467 | [% FOREACH item = hash %][% item %] |
468 | [% END %][% END %] |
469 | |
470 | [% MACRO printList(array) BLOCK %][% FOREACH item = array %][% item %] [% END %][% END %] |
471 | |
472 | |
473 | [% ###### DOCUMENT START ###### %] |
474 | |
475 | package Durian::Model::DBI; |
476 | |
477 | # Created by SQL::Translator::Producer::ClassDBI |
478 | # Template used AutoDBI.tt2 |
479 | |
480 | use strict; |
481 | use base qw(Class::DBI::Pg); |
482 | |
483 | Durian::Model::DBI->set_db('Main', '[% db_str %]', '[% db_user %]', '[% db_pass %]'); |
484 | |
485 | [% FOREACH package = packages %] |
486 | [% printPackage(package.value) %] |
487 | [% END %] |
488 | EOF |
489 | |
490 | my $turnkey_xml_tt2 = <<EOF; |
491 | <?xml version="1.0" encoding="UTF-8"?> |
492 | <!DOCTYPE Durian SYSTEM "Durian.dtd"> |
493 | <Durian> |
494 | |
495 | <!-- The basic layout is fixed --> |
496 | <container bgcolor="#FFFFFF" cellpadding="0" cellspacing="0" height="90%" orientation="vertical" type="root" width="100%" xlink:label="RootContainer"> |
497 | <container cellpadding="3" cellspacing="0" orientation="horizontal" type="container" height="100%" width="100%" xlink:label="MiddleContainer"> |
498 | <container align="center" cellpadding="2" cellspacing="0" class="leftbar" orientation="vertical" type="minor" width="0%" xlink:label="MidLeftContainer"/> |
499 | <container cellpadding="0" cellspacing="0" orientation="vertical" width="100%" type="major" xlink:label="MainContainer"/> |
500 | </container> |
501 | </container> |
502 | |
503 | <!-- Atom Classes --> |
504 | [% FOREACH package = linkable %] |
505 | <atom class="Durian::Atom::[% package.key FILTER ucfirst %]" name="[% package.key FILTER ucfirst %]" xlink:label="[% package.key FILTER ucfirst %]Atom"/> |
69c7a62f |
506 | [%- END -%] |
c00bb9f8 |
507 | |
508 | <!-- Atom Bindings --> |
509 | <atomatombindings> |
510 | [% FOREACH focus_atom = linkable %] |
511 | [% FOREACH link_atom = focus_atom.value %] |
512 | <atomatombinding xlink:from="#[% focus_atom.key FILTER ucfirst %]Atom" xlink:to="#[% link_atom.key FILTER ucfirst %]Atom" xlink:label="[% focus_atom.key FILTER ucfirst %]Atom2[% link_atom.key FILTER ucfirst %]Atom"/> |
69c7a62f |
513 | [%- END -%] |
514 | [%- END -%] |
c00bb9f8 |
515 | </atomatombindings> |
516 | |
517 | <atomcontainerbindings> |
69c7a62f |
518 | [% FOREACH focus_atom = linkable %] |
519 | <atomcontainerbindingslayout xlink:label="Durian::Model::[% focus_atom.key FILTER ucfirst %]"> |
520 | [% FOREACH link_atom = focus_atom.value %] |
521 | <atomcontainerbinding xlink:from="#MidLeftContainer" xlink:label="MidLeftContainer2[% link_atom.key FILTER ucfirst %]Atom" xlink:to="#[% link_atom.key FILTER ucfirst %]Atom"/> |
522 | [%- END -%] |
523 | <atomcontainerbinding xlink:from="#MainContainer" xlink:label="MainContainer2[% focus_atom.key FILTER ucfirst %]Atom" xlink:to="#[% focus_atom.key FILTER ucfirst %]Atom"/> |
524 | </atomcontainerbindingslayout> |
525 | [%- END -%] |
526 | </atomcontainerbindings> |
527 | |
528 | <uribindings> |
529 | <uribinding uri="/" class="Durian::Util::Frontpage"/> |
530 | </uribindings> |
531 | |
532 | <classbindings> |
533 | [% FOREACH focus_atom = linkable %] |
534 | <classbinding class="Durian::Model::[% focus_atom.key FILTER ucfirst %]" plugin="#[% focus_atom.key FILTER ucfirst %]Atom" rank="0"/> |
535 | [%- END -%] |
c00bb9f8 |
536 | |
69c7a62f |
537 | </classbindings> |
c00bb9f8 |
538 | |
539 | </Durian> |
540 | EOF |
541 | |
542 | my $turnkey_template_tt2 = <<'EOF'; |
543 | [% TAGS [- -] %] |
544 | [% MACRO renderpanel(panel,dbobject) BLOCK %] |
545 | <!-- begin panel: [% panel.label %] --> |
546 | <table border="0" width="[% panel.width %]" height="[% panel.height %]" bgcolor="[% panel.bgcolor %]" valign="top" cellpadding="[% panel.cellpadding %]" cellspacing="[% panel.cellspacing %]" align="[% panel.align %]" valign="[% panel.valign %]"> |
547 | <tr> |
548 | [% FOREACH p = panel.containers %] |
549 | [% IF p.can_render(panel) %] |
550 | <td valign="top" class="[% p.class %]" align="[% panel.align %]" height="[% p.height || 1 %]" width="[% p.width %]"> |
551 | [% IF p.type == 'Container' %] |
552 | [% renderpanel(p,dbobject) %] |
553 | [% ELSE %] |
554 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"> |
555 | [% IF p.name %] |
556 | <tr bgcolor="#4444FF" height="1"> |
557 | <td><font color="#FFFFFF">[% p.name %][% IF panel.type == 'major' %]: [% dbobject.name %][% END %]</font></td> |
558 | <td align="right" width="0"><!--<nobr><img src="/images/v.gif"/><img src="/images/^.gif"/>[% IF p.delible == 'yes' %]<img src="/images/x.gif"/>[% END %]</nobr>--></td> |
559 | </tr> |
560 | [% END %] |
561 | <tr><td colspan="2" bgcolor="#FFFFFF"> |
562 | <!-- begin atom: [% p.label %] --> |
563 | <table cellpadding="0" cellspacing="0" align="left" height="100%" width="100%"><!-- [% ref(atom) %] [% ref(dbobject) %] --> |
564 | [% renderatom(p,dbobject) %] <!-- used to be renderplugin(p,panel) --> |
565 | </table> |
566 | </table> |
567 | [% END %] |
568 | </td> |
569 | [% IF panel.orientation == 'vertical' %] |
570 | </tr><tr> |
571 | [% END %] |
572 | [% END %] |
573 | [% END %] |
574 | </tr> |
575 | </table> |
576 | <!-- end panel: [% panel.label %] --> |
577 | [% END %] |
578 | [% MACRO renderatom(atom, dbobject) SWITCH atom.name %] |
579 | [- FOREACH package = linkable -] |
580 | [% CASE '[- package.key FILTER ucfirst -]' %] |
581 | [% render[- package.key FILTER ucfirst -]Atom(atom.render(dbobject)) %] |
582 | [- END -] |
583 | [% CASE DEFAULT %] |
584 | [% renderlist(atom.render(dbobject)) %] |
585 | [% END %] |
586 | [- FOREACH package = linkable -] |
587 | [% MACRO render[- package.key FILTER ucfirst -]Atom(lstArr) BLOCK %] |
588 | [% FOREACH record = lstArr %] |
589 | [% fields = record.data %] |
590 | [- pname = package.key FILTER ucfirst -] |
591 | [- pkey = "Durian::Model::${pname}" -] |
592 | [- FOREACH field = packages.$pkey.columns_essential -] |
593 | <tr><td><b>[- field -]</b></td><td>[% fields.[- field -] %]</td></tr> |
594 | [- END -] |
595 | [% id = record.id %] |
596 | <tr><td><a href="?id=[% id %];class=Durian::Model::[- package.key FILTER ucfirst -]">Link</a></td><td></td></tr> |
597 | [% END %] |
598 | [% END %] |
599 | [- END -] |
600 | [% MACRO renderlist(lstArr) BLOCK %] |
601 | [% FOREACH item = lstArr %] |
602 | <tr>[% item %]</tr> |
603 | [% END %] |
604 | [% END %] |
605 | EOF |
606 | |
607 | sub translateForm |
608 | { |
609 | my $t = shift; |
610 | my $output = shift; |
611 | my $args = $t->producer_args; |
612 | my $tt2 = $args->{'template'}; |
613 | my $tt2Ref; |
69c7a62f |
614 | |
615 | if ($tt2 eq 'atom') { $tt2Ref = \$turnkey_atom_tt2; } |
616 | elsif ($tt2 eq 'classdbi') { $tt2Ref = \$turnkey_dbi_tt2; } |
617 | elsif ($tt2 eq 'xml') { $tt2Ref = \$turnkey_xml_tt2; } |
618 | elsif ($tt2 eq 'template') { $tt2Ref = \$turnkey_template_tt2; } |
619 | else { die __PACKAGE__." didn't recognize your template option: $tt2" } |
c00bb9f8 |
620 | |
621 | my $vars = { |
622 | packages => $output->{packages}, |
623 | linkable => $output->{linkable}, |
624 | linktable => $output->{linktable}, |
625 | db_str => $args->{db_str}, |
626 | db_user => $args->{db_user}, |
627 | db_pass => $args->{db_pass}, |
628 | }; |
629 | my $config = { |
630 | EVAL_PERL => 1, # evaluate Perl code blocks |
631 | }; |
632 | |
633 | # create Template object |
634 | my $template = Template->new($config); |
635 | |
636 | my $result; |
637 | # specify input filename, or file handle, text reference, etc. |
638 | # process input template, substituting variables |
639 | $template->process($tt2Ref, $vars, \$result) || die $template->error(); |
640 | return($result); |
641 | } |
642 | |
643 | 1; |
644 | |
645 | # ------------------------------------------------------------------- |
646 | |
647 | =pod |
648 | |
649 | =head1 NAME |
650 | |
651 | SQL::Translator::Producer::ClassDBI - create Class::DBI classes from schema |
652 | |
653 | =head1 SYNOPSIS |
654 | |
655 | Use this producer as you would any other from SQL::Translator. See |
656 | L<SQL::Translator> for details. |
657 | |
69c7a62f |
658 | This package utilizes SQL::Translator\'s formatting methods |
c00bb9f8 |
659 | format_package_name(), format_pk_name(), format_fk_name(), and |
660 | format_table_name() as it creates classes, one per table in the schema |
661 | provided. An additional base class is also created for database connectivity |
662 | configuration. See L<Class::DBI> for details on how this works. |
663 | |
664 | =head1 AUTHORS |
665 | |
666 | Allen Day E<lt>allenday@ucla.eduE<gt> |
667 | Ying Zhang E<lt>zyolive@yahoo.comE<gt>, |
668 | Ken Y. Clark E<lt>kclark@cpan.orgE<gt>, |
69c7a62f |
669 | Brian O\'Connor E<lt>brian.oconnor@excite.comE<gt>. |