File Coverage

blib/lib/Java/Javap/TypeCast.pm
Criterion Covered Total %
statement 9 62 14.5
branch 0 12 0.0
condition n/a
subroutine 3 12 25.0
pod 7 8 87.5
total 19 94 20.2


line stmt bran cond sub pod time code
1             package Java::Javap::TypeCast;
2              
3             =head1 NAME
4              
5             Java::Javap::TypeCast - map Java types to Perl 6 equivalents
6              
7             =head1 SYNOPSIS
8              
9             use Java::Javap::TypeCast;
10              
11             $type_caster = Java::Javap::TypeCast->new();
12              
13             $perl_type = $type_caster->cast( $java_type );
14              
15             =head1 DESCRIPTION
16              
17             Provides a mechanism to map java type names (classes and interfaces) into
18             corresponding perl type names (typically roles).
19              
20             =head1 METHODS
21              
22             =cut
23              
24 7     7   36 use strict;
  7         11  
  7         215  
25 7     7   35 use warnings;
  7         10  
  7         162  
26              
27 7     7   33 use Carp;
  7         14  
  7         6094  
28              
29             =head2 new
30              
31             $type_caster = Java::Javap::TypeCast->new();
32              
33             Returns a new type caster instance with a default set of type casts.
34              
35             The default set of type mappings should I be relied upon as it's likely to
36             change over time with unpredictable results for your application. You should call
37             L and perhaps a method like L to
38             load in your own set of type mappings.
39              
40             =cut
41              
42             sub new {
43 0     0 1   my $class = shift;
44 0           my $self = bless { }, $class;
45 0           $self->_add_type_casts_from_DATA();
46 0           return $self;
47             }
48              
49             =head2 set_type_casts
50              
51             $self->set_type_casts(\%hash)
52              
53             Replaces the current set of type casts with the specified set.
54              
55             =cut
56              
57             sub set_type_casts {
58 0     0 1   my ($self, $new_casts) = @_;
59 0           $self->{casts} = { %$new_casts };
60 0           return;
61             }
62              
63              
64             =head2 add_type_casts
65              
66             $self->add_type_casts(\%hash)
67              
68             Adds the specified set of type casts to the current set, overriding any that
69             have the same names.
70              
71             =cut
72              
73             sub add_type_casts {
74 0     0 1   my ($self, $new_casts) = @_;
75             $self->{casts}{$_} = $new_casts->{$_}
76 0           for keys %$new_casts;
77 0           return;
78             }
79              
80              
81             =head2 add_type_casts_from_filehandle
82              
83             $self->add_type_casts_from_filehandle($fh, $name)
84              
85             Reads lines defining type mappings from the specified filehandle.
86             Each is specified as two non-blank fields separated by whitespace.
87             The first specified a Java type and the second a corresponding Perl type.
88             Comments starting with a # character are ignored, as are blank lines.
89              
90             A warning is issued for lines that aren't in the correct format.
91             The $name argument is only used in that warnig message.
92              
93             =cut
94              
95             sub add_type_casts_from_filehandle {
96 0     0 1   my ($self, $fh, $name) = @_;
97 0           while (<$fh>) {
98 0           chomp;
99 0           s/#.*//; # remove comments
100 0 0         next if m/^ \s* $/x; # ignore blank lines
101 0           my @items = split /\s+/;
102 0 0         if (@items != 2) {
103 0           warn "Ignored line $. in $name: $_\n";
104 0           next;
105             }
106 0           my ($javatype, $perltype) = @items;
107 0           $self->{casts}{$javatype} = $perltype;
108             }
109             }
110              
111             =head2 add_type_casts_from_file
112              
113             $self->add_type_casts_from_file($filename)
114              
115             Opens $filename for reading and calls L.
116              
117             =cut
118              
119             sub add_type_casts_from_file {
120 0     0 1   my ($self, $filename) = @_;
121 0 0         open my $fh, '<', $filename
122             or croak "Unable to open '$filename' for reading: $!";
123 0           return $self->add_type_casts_from_filehandle($fh, $filename);
124             }
125              
126              
127             # _add_type_casts_from_DATA - private
128              
129             sub _add_type_casts_from_DATA {
130 0     0     my ($self, $filename) = @_;
131 0           local $.; # don't add chunk/filename to future warning messages
132 0           my $position = tell( DATA );
133 0           $self->add_type_casts_from_filehandle(\*DATA, 'default DATA');
134 0           seek DATA, $position, 0; # Reset the filehandle for next time
135 0           return;
136             }
137              
138              
139             =head2 cast
140              
141             $perl_type = $type_caster->defined_cast( $java_type );
142              
143             Returns a perl type for the corresponding java type argument if an type mapping
144             has been defined, else undef.
145              
146             Firstly the java type is looked up verbatim in the type mapping.
147             If a defined value is found then it's returned.
148              
149             If there's no verbatim match for the full type name then defined_cast() checks for
150             wildcard matches by removing trailing words and appending a '*'. For example,
151             if there's no entry for 'sun.lang.annotation.foo' the defined_cast() would look for
152             each of these in turn:
153              
154             sun.lang.annotation.foo
155             sun.lang.annotation.*
156             sun.lang.*
157             sun.*
158             *
159              
160             =cut
161              
162             sub defined_cast {
163 0     0 0   my $self = shift;
164 0           my $java_type = shift;
165            
166 0           my $casts = $self->{casts};
167              
168 0           my $perl6_type = $casts->{ $java_type };
169              
170 0 0         if (not defined $perl6_type) {
171             # no specific type cast so look for wildcard ones
172 0           my @parts = split /\./, $java_type;
173 0           while (@parts) {
174 0           $parts[-1] = '*'; # replace last word with *
175 0           $perl6_type = $casts->{ join '.', @parts };
176 0 0         last if defined $perl6_type;
177 0           pop @parts;
178             }
179             }
180              
181 0           return $perl6_type;
182             }
183              
184              
185              
186             =head2 fallback_cast()
187              
188             $perl_type = $type_caster->cast( $java_type );
189              
190             Returns a perl type for the corresponding java type argument by editing the
191             java type name, without consulting the type mapping.
192            
193             - dots are changed to double colons
194             - dollar symbols are changed to _PRIVATE_
195              
196             =cut
197              
198             sub fallback_cast {
199 0     0 1   my $self = shift;
200 0           my $java_type = shift;
201              
202 0           (my $perl6_type = $java_type) =~ s/\./::/g;
203 0           $perl6_type =~ s/\$/_PRIVATE_/g; # handle '$' in type names
204              
205 0           return $perl6_type;
206             }
207              
208              
209             =head2 cast
210              
211             $perl_type = $type_caster->cast( $java_type );
212              
213             Returns the result of calling L, if defined, else returns the
214             result of calling L.
215              
216             =cut
217              
218             sub cast {
219 0     0 1   my $self = shift;
220 0           my $java_type = shift;
221 0           my $perl6_type = $self->defined_cast($java_type);
222              
223 0 0         if (not defined $perl6_type) {
224 0           $perl6_type = $self->fallback_cast($java_type);
225             }
226              
227 0           return $perl6_type;
228             }
229              
230             =head1 AUTHOR
231              
232             Tim Bunce, Etim.bunce@pobox.comE,
233             Phil Crow, Ecrow.phil@gmail.comE
234              
235             =head1 COPYRIGHT AND LICENSE
236              
237             Copyright (C) 2010, Tim Bunce
238             Copyright (C) 2007, Phil Crow
239              
240             This library is free software; you can redistribute it and/or modify
241             it under the same terms as Perl itself, either Perl version 5.8.6 or,
242             at your option, any later version of Perl 5 you may have available.
243              
244             =cut
245              
246             1;
247              
248             __DATA__