File Coverage

blib/lib/Template/Plugin/Java/Utils.pm
Criterion Covered Total %
statement 24 121 19.8
branch 0 70 0.0
condition 0 13 0.0
subroutine 8 20 40.0
pod 10 10 100.0
total 42 234 17.9


line stmt bran cond sub pod time code
1             package Template::Plugin::Java::Utils;
2              
3             =head1 NAME
4              
5             Template::Plugin::Java::Utils - Utility functions for Template::Plugin::Java.
6              
7             =head1 SYNOPSIS
8              
9             use Template::Plugin::Java::Utils qw/list of subroutines to import/;
10              
11             =head1 SUBROUTINES
12              
13             =over 8
14              
15             =cut
16              
17             @EXPORT_OK = qw(
18             parseOptions sqlType2JavaType simplifyPath findPackageDir isNum
19             castJavaString determinePackage createTemplate parseCmdLine
20             javaTypeName
21             );
22              
23 1     1   11 use strict;
  1         2  
  1         42  
24 1     1   6 use base qw(Exporter);
  1         2  
  1         126  
25 1     1   5 use Carp;
  1         2  
  1         84  
26 1     1   816 use Template::Plugin::Java::Constants qw/:all/;
  1         3  
  1         157  
27              
28             =item B
29              
30             Creates a new Template with reasonable options.
31              
32             =cut
33             sub createTemplate {
34 1     1   3946 use Template;
  1         74031  
  1         53  
35 1     1   14 use Template::Constants qw/:status/;
  1         2  
  1         1928  
36 0 0   0 1   my %options = ref $_[0] ? %{+shift} : @_
  0 0          
37             if $_[0];
38            
39             # Enable template compilation if version of Template is 2 or greater.
40 0 0         if ($Template::VERSION !~ /^[01]/) {
41 0           $options{COMPILE_EXT} = '.compiled';
42             }
43              
44             my $template = new Template({
45             INTERPOLATE => 1,
46             EVAL_PERL => 1,
47             PRE_CHOMP => 1,
48             RECURSION => 1,
49             INCLUDE_PATH => $ENV{TEMPLATEPATH},
50             CATCH => {'default' => sub {
51 0     0     my ($context, $type, $info) = @_;
52 0           print STDERR "Error generating class "
53             . $context->stash->get("class")
54             . ":\n\t$type: $info\n\n\n";
55 0           return STATUS_STOP;
56             }},
57 0           %options
58             });
59              
60 0           return $template;
61             }
62              
63             =item B
64              
65             Replaces c_c with cC and nosomething=whatever with something=0 in the keys of a
66             hash.
67              
68             =cut
69             sub parseOptions {
70 0     0 1   my %options = ();
71              
72 0 0 0       if (@_ > 1) {
    0          
73 0           %options = @_;
74             } elsif (defined $_[0] and UNIVERSAL::isa($_[0], 'HASH')) {
75 0           %options = %{+shift};
  0            
76             }
77              
78 0           for my $option (keys %options) {
79 0 0         if ($option =~ /^no(.*)/) {
80 0           delete $options{$option};
81 0           $option = $1;
82 0           $options{$option} = 0;
83             }
84 0 0         if (($_ = $option) =~ s/_(\w)/\U$1/g) {
85 0           $options{$_} = delete $options{$option};
86             }
87             }
88              
89 0 0         return wantarray ? %options : \%options;
90             }
91              
92             =item B
93              
94             Adds to or sets an option in a hash, supports nested arrays and boolean
95             options. The logic here is one of those things that just works the way it is
96             and seems decipherable, but don't mess with it.
97              
98             =cut
99             sub setOption (\%$;$) {
100 0     0 1   my ($options, $option, $value) = @_;
101              
102 0 0         if (not exists $options->{$option}) {
    0          
    0          
    0          
    0          
    0          
103 0   0       $options->{$option} = $value || TRUE;
104             } elsif (not ref $options->{$option}) {
105 0 0 0       if ($options->{$option} ne TRUE && $value) {
    0          
106 0           $options->{$option} = [ $options->{$option}, $value ];
107             } elsif (not $value) {
108 0           return;
109             } else {
110 0           $options->{$option} = $value;
111             }
112             } elsif (not $value) {
113 0           return;
114             } elsif (ref $options->{$option} eq 'ARRAY') {
115 0           push @{$options->{$option}}, $value;
  0            
116             } elsif (ref $options->{$option} eq 'HASH') {
117 0           $options->{$option}{$value} = TRUE;
118             } elsif (UNIVERSAL::can($options->{$option}, $value)) {
119 0           $options->{$option}->$value();
120             }
121             }
122              
123             =item B
124              
125             Parses @ARGV into a hash of options and values, leaving everything else that
126             is most likely a list of files on @ARGV.
127              
128             =cut
129             sub parseCmdLine () {
130 0     0 1   my (%options, @files);
131              
132 0           my ($value, $last_option, $last_option_had_value);
133              
134 0           while (defined ($_ = shift @ARGV)) {
135 0 0         last if /^--$/;
136              
137 0 0 0       if (/^[-+]+(.*)=?(.*)/) {
    0          
138 0           $last_option = $1;
139 0           $value = $2;
140 0           setOption %options, $last_option, $value;
141 0 0         $last_option_had_value = $2 ? TRUE : FALSE;
142             } elsif ((not $last_option_had_value) && $last_option) {
143 0           setOption %options, $last_option, $_;
144 0           $last_option_had_value = TRUE;
145             } else {
146 0           push @files, $_;
147             }
148             }
149              
150 0           push @ARGV, @files;
151 0           return \%options;
152             }
153              
154             =item B
155              
156             Maps some ANSI SQL data types to the closest Java variable types. The default
157             case is byte[] for unrecognized sql types.
158              
159             =cut
160             sub sqlType2JavaType ($;$) {
161 0     0 1   ($_, my $precision) = @_;
162              
163 0 0         /^.*char$/i && return 'String';
164 0 0         /^integer$/i && return 'int';
165 0 0         /^bigint$/i && return 'long';
166 0 0         /^smallint$/i && return 'short';
167              
168 0 0         /^numeric$/i && do {
169 0 0         $precision <= 5 && return 'short';
170 0 0         $precision <= 10&& return 'int';
171 0           return 'long';
172             };
173              
174 0 0         /^date$/i && return 'Date';
175              
176 0           return 'byte[]';
177             }
178              
179             =item B
180              
181             Remove any dir/../ or /./ or extraneous / from a path, as well as prepending
182             the current directory if necessary.
183              
184             =cut
185             sub simplifyPath ($) {
186 1     1   18330 use URI::file;
  1         22013  
  1         804  
187 0     0 1   my $path = shift;
188              
189 0           return URI::file->new_abs($path)->file;
190             }
191              
192             =item B
193              
194             Find package in $ENV{CLASSPATH}.
195              
196             =cut
197             sub findPackageDir ($) {
198 0     0 1   my $package = shift;
199 0           my $classpath = $ENV{CLASSPATH};
200 0           my @classpath = split /:/, $classpath;
201 0           my @package = split /\./, $package;
202 0           my $package_dir = join ("/", @package) . "/";
203              
204             # Find the first match in CLASSPATH.
205 0           for (map { "$_/$package_dir" } @classpath) {
  0            
206 0 0         return $_ if -d;
207             }
208              
209 0           return "";
210             }
211              
212             =item B
213              
214             Determine the package of the current or passed-in directory.
215              
216             =cut
217             sub determinePackage (;$) {
218 0   0 0 1   my $dir = shift || ".";
219 0           my @cwd = split m|/|, substr ( simplifyPath $dir, 1 );
220              
221 0           my $i = @cwd;
222 0           while ($i--) {
223 0           my $package = join ('.', @cwd[$i..$#cwd]);
224              
225 0 0         if (findPackageDir $package) {
226 0           return $package;
227             }
228             }
229              
230 0           return join ('.', @cwd); # If all else fails.
231             }
232              
233             =item B
234              
235             Determines whether a string is a number or not. Uses the more powerful
236             DBI::looks_like_number heuristic if available.
237              
238             =cut
239             my $isNum_body;
240             eval { require DBI };
241             if (not $@ && DBI->can('looks_like_number')) {
242             $isNum_body = sub {
243 0 0   0     if (DBI::looks_like_number( shift )) {
244 0           return TRUE;
245             } else {
246 0           return FALSE;
247             }
248             };
249             } else {
250             $isNum_body = sub {
251             local $^W = undef if $^W;
252             $_ = shift;
253              
254             if (not defined $_) {
255             return FALSE;
256             } elsif ($_ != 0 or /^0*(?:\.0*)$/) {
257             return TRUE;
258             } else {
259             return FALSE;
260             }
261             }
262             }
263              
264             # Install the sub reference as the sub.
265             {
266 1     1   12 no strict 'refs';
  1         2  
  1         617  
267              
268             *{__PACKAGE__.'::isNum'} = $isNum_body;
269             }
270              
271             =item B
272              
273             Casts a java String to another type using the appropriate code.
274              
275             =cut
276             sub castJavaString {
277 0     0 1   my ($name, $type) = @_;
278              
279 0           for ($type) {
280 0 0         /String/&& do { return $name };
  0            
281 0 0         /int/ && do { return "Integer.parseInt($name)" };
  0            
282 0 0         /@{[SCALAR]}/ && do {
  0            
283 0           my $type = $1;
284 0 0         if ($type =~ /^[A-Z]/) {
285 0           return "new $type($name)";
286             } else {
287 0           return "\u$type.parse\u$type($name)";
288             }
289             };
290 0           die "Cannot cast $name from String to $type.";
291             }
292             }
293              
294             =item B
295              
296             Transform a java type name to a character string version. In other words,
297             String remains String, but byte[] becomes byteArray.
298              
299             =cut
300             sub javaTypeName ($) {
301 0     0 1   local $_ = pop;
302 0           s/\[\]/Array/g;
303              
304 0           return $_;
305             }
306              
307             1;
308              
309             __END__