File Coverage

blib/lib/Template/Plugin/Java.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Template::Plugin::Java;
2              
3             ($VERSION) = '$ProjectVersion: 0.4 $' =~ /\$ProjectVersion:\s+(\S+)/;
4              
5             =head1 NAME
6              
7             Template::Plugin::Java - Generate Java Classes from XML description files and templates.
8              
9             =head1 SYNOPSIS
10              
11             From an xml file such as:
12              
13            
14            
15             value2
16            
17             10
18             String
19            
20             20
21            
22            
23              
24             Through the program "tjava":
25              
26             tjava [options] [file.xml ...]
27              
28             Via a template, such as:
29              
30             [% USE Java %]
31             package $package;
32            
33             public class $class {
34            
35             [% FOREACH Java.variables %]
36             $type $name = $initializer;
37             [% END %]
38            
39             //... etc
40             }
41              
42             To generated Java source code in the appropriate directory as determined by the
43             package of the .xml file's directory, specified package option if any, and
44             CLASSPATH.
45              
46             =head1 OPTIONS
47              
48             Any options may be given besides those listed, these are passed directly to the
49             Templates being processed in the stash (the variable table at time of
50             processing). They can be given in the ... section of an XML
51             file (in which case, don't use the -- dashes) as attributes or elements, or on
52             the command line.
53              
54             =over 8
55              
56             =item B<--template>
57              
58             Name of the template to process. No extension is assumed by default unlike in
59             the previous version.
60              
61             =item B<--package>
62              
63             Destination package to put the generated classes, otherwise will be determined
64             from how the current directory relates to the CLASSPATH.
65              
66             =item B<--class>
67              
68             Class name to use, otherwise will infer from the root tag of the XML file.
69              
70             =item B<--templatePath>
71              
72             Colon separated path where the templates can be found, overrides the
73             environment variable TEMPLATEPATH. This doesn't work right now, so use the
74             TEMPLATEPATH environment variable.
75              
76             =item B<--genContainers>
77              
78             If set to 0, classes for subcontainers will not be generated. This is generally
79             not useful.
80              
81             =item B<--containerTemplate>
82              
83             By default set to F, this is the default template, as well
84             as the template used for sub-containers.
85              
86             =item B<--containerNamePrefix>
87              
88             By default, if generating class Foo that needs to have a sub container wrapped
89             in tag , it's name will be FooBar. This is safe and won't cause collisions
90             with different classes having sub containers of the same name (until some sort
91             of dependency checking code is introduced). To turn this off, set it to the
92             empty string "".
93              
94             =item B<--interface>
95              
96             Interface to add to list of implemented interfaces, can be supplied multiple
97             times. Make sure you append any necessary code to implement any of these
98             interfaces.
99              
100             =item B<--append>
101              
102             Text to insert in the generated class body.
103              
104             =item B<--appendFile>
105              
106             Will insert text read from the file specified into the generated class body.
107             This option and the B<--append> option are mutually exclusive.
108              
109             =item B<--file[s]>
110              
111             The XML file(s) to parse. This is useful for when the Plugin is instantiated
112             from a custom script, not via tjava or inside a template.
113              
114             Any other option will be placed into the stash for the templates to use, making
115             tjava very useful with your custom templates.
116              
117             Anything that's not an option will be assumed to be a file.
118              
119             =back
120              
121             =head1 DESCRIPTION
122              
123             Template::Plugin::Java is a plugin module for the Template toolkit that makes
124             it easier to write templates for generating Java source code, ultimately for
125             transforming XML descriptions into Java language sources.
126              
127             It can be used either directly on the command line, or loaded from a Template
128             with a C<[% USE Java %]> statement, or in many other ways. It tries to be
129             intelligent and figure out what context you are using it in.
130              
131             I'll write more eventually, for now see the examples in the distribution.
132              
133             =head1 METHODS
134              
135             =over 8
136              
137             =cut
138              
139             require Template::Plugin;
140             @ISA = 'Template::Plugin';
141              
142 1     1   1105 use strict;
  1         2  
  1         202  
143 1     1   7 use Carp qw/verbose croak/;
  1         1  
  1         225  
144 1         122 use Template::Plugin::Java::Utils qw(
145             parseOptions findPackageDir isNum determinePackage createTemplate
146             parseCmdLine javaTypeName
147 1     1   863 );
  1         3  
148 1     1   5 use Template::Plugin::Java::Constants qw/:all/;
  1         2  
  1         176  
149              
150             =item B
151              
152             This, the constructor, does everything necessary to create a new instance of
153             the Java plugin, based on context. If not given a context, takes control of the
154             command line and then parses any options and files given. This is what the
155             "tjava" utility does.
156              
157             =cut
158             sub new {
159 1     1   2304 use XML::Simple;
  0            
  0            
160             use File::Basename;
161              
162             my $class = shift;
163             my $self = bless {}, ref $class || $class;
164             my $context;
165             my $params = {};
166             my $arg1 = $_[0];
167              
168             if (@_ <= 1 && not ref $arg1) {
169             $params->{file} = shift;
170             } elsif (not ref $arg1) {
171             $params = {@_};
172             } elsif (UNIVERSAL::isa($arg1, 'Template::Context')) {
173             $self->context(shift);
174             } elsif (UNIVERSAL::isa($arg1, 'HASH')) {
175             $params = { %{+shift}, @_ };
176             }
177              
178             $self->context(delete $params->{context});
179              
180             my $defaults = delete $params->{defaults} || {};
181             my $cmd_line = delete $params->{cmdLine} || {};
182              
183             # Automatically parse the command line unless either explicitly told not to, or
184             # a the object has been created inside a template as an actual plugin.
185             unless ((exists $params->{parseCmdLine}
186             && (not $params->{parseCmdLine}))
187             || $self->context) {
188             $cmd_line = {
189             %$cmd_line,
190             parseOptions( parseCmdLine )
191             };
192              
193             # Use rest of @ARGV as files.
194             push @{$params->{files}}, @ARGV;
195             @ARGV = ();
196             }
197              
198             unless ($self->context) {
199             $self->template (
200             createTemplate delete $params->{templateOptions}
201             );
202             }
203              
204             my $files = delete $params->{file} || delete $params->{files};
205              
206             my @files;
207             if (defined $files) {
208             if (UNIVERSAL::isa($files, 'ARRAY')) {
209             @files = @$files;
210             } else {
211             push @files, $files;
212             }
213             }
214              
215             # The ! eof STDIN is necessary here, because sub-templates will want to create
216             # new instances of this Plugin, when the process still has a redirected STDIN,
217             # just with no data to read. Using eof on a terminal is bad, but this doesn't
218             # happen because of the && short circuit.
219             if (scalar @files == 0 && ! -t STDIN && ! eof STDIN) {
220             push @files, '-';
221             }
222              
223             for my $file_name (@files) {
224             my $stash;
225              
226             if ($file_name ne '-') {
227             # Prepend ./ if relative path.
228             $file_name =~ s!^([^/-])!./$1!;
229             $stash = XMLin (
230             $file_name,
231             keyattr => "",
232             keeproot => 1,
233             cache => 'storable'
234             );
235             } else {
236             # Reading from STDIN.
237             my $data;
238             {
239             local @ARGV = '-';
240             $data = join '', <>;
241             }
242             $stash = XMLin (
243             $data,
244             keyattr => "",
245             keeproot => 1,
246             );
247             }
248              
249             my $root = (keys %$stash)[0];
250             $stash = {%{$stash->{$root}}};
251              
252             my $context = delete $stash->{'java:'} || {};
253              
254             $stash = {
255             parseOptions(
256             %$defaults,
257             %$params,
258             %$context,
259             %$cmd_line
260             ),
261             variables => $stash
262             };
263              
264             $stash->{tag} = $root;
265             $stash->{class} ||= ucfirst $root;
266              
267             # Allow nopackage="true" to create a class that isn't in a package.
268             {
269             # Turn off warnings about comparing uninitialized values.
270             local $^W = undef;
271              
272             if (!$stash->{package} && $stash->{package} ne '0') {
273             $stash->{package} =
274             determinePackage dirname($file_name);
275             }
276             }
277              
278             $stash->{genContainers} ||= TRUE;
279             $stash->{containerTemplate} ||= 'Container';
280             $stash->{template} ||= $stash->{containerTemplate};
281              
282             $stash->{containerNamePrefix} = $stash->{class}
283             if not exists $stash->{containerNamePrefix};
284              
285             if (exists $stash->{appendFile}) {
286             use IO::File;
287             my $file = new IO::File $stash->{appendFile}
288             or die "Could not open $stash->{appendFile}";
289             local $/ = undef;
290             $stash->{append} .= <$file>;
291             }
292              
293             $self->genClass($stash);
294             }
295              
296             return $self;
297             }
298              
299             =item B