File Coverage

blib/lib/SOAP/DirectI/Serialize.pm
Criterion Covered Total %
statement 104 114 91.2
branch 21 40 52.5
condition 14 29 48.2
subroutine 19 20 95.0
pod 0 13 0.0
total 158 216 73.1


line stmt bran cond sub pod time code
1             #
2             #===============================================================================
3             #
4             # FILE: Serialize.pm
5             #
6             # DESCRIPTION: SOAP::DirectI::Serialize -- serialization of requests to DirectI
7             #
8             # FILES: ---
9             # BUGS: ---
10             # NOTES: ---
11             # AUTHOR: Pavel Boldin (),
12             # COMPANY:
13             # VERSION: 1.0
14             # CREATED: 18.03.2009 13:38:32 MSK
15             # REVISION: ---
16             #===============================================================================
17              
18             package SOAP::DirectI::Serialize;
19              
20 2     2   52810 use strict;
  2         4  
  2         127  
21 2     2   11 use warnings;
  2         4  
  2         71  
22              
23 2     2   9 use Carp;
  2         3  
  2         5445  
24              
25             sub hash_to_soap {
26 1     1 0 66 my $self = shift;
27 1         1 my ($data, $signature) = @_;
28              
29 1         2 my @output;
30              
31 1         10 push @output, $self->request_prefix( $signature );
32              
33 1         3 my $args = $signature->{ args };
34              
35 1         4 push @output, $self->serialize_args( $args, $data );
36              
37 1         4 push @output, $self->request_suffix( $signature );
38              
39             #warn @output;
40              
41 1         6 return join '', @output;
42             }
43              
44             sub serialize_args {
45 1     1 0 2 my $self = shift;
46 1         2 my $args = shift;
47 1         2 my $data = shift;
48              
49 1         1 my @output;
50              
51 1         3 foreach my $arg (@$args) {
52 3         4 my $hash_key = $arg->{hash_key };
53 3         5 my $key = $arg->{key };
54              
55 3 50       7 if ( not $hash_key ) {
56 3         21 $hash_key = join '_', map { lc $_ } ($key =~ m/([A-Z]?[a-z0-9]+)/g);
  11         22  
57             }
58              
59 3 50 33     15 if ( ! exists $data->{ $hash_key } && $arg->{required} ) {
60 0         0 croak "Required field $key missed";
61             }
62              
63             #warn $hash_key;
64              
65 3         6 my $d = $data->{ $hash_key };
66             # NOTE FUCKING RECURSION!
67 3 50 33     9 if ( ! $d && (my $s = $self->can('_default_value_'.$hash_key)) ) {
68 0         0 $d = $s->( $self, $arg, $data );
69             }
70             #my $t = $arg ->{ type };
71              
72 3         10 push @output, $self->serialize( $arg, $d );
73             }
74              
75 1         2 return @output;
76             }
77              
78              
79             sub request_prefix {
80 1     1 0 2 my ($self, $signature) = @_;
81              
82 1   50     8 $signature->{namespace} ||= 'com.logicboxes.foundation.sfnb.user.Customer';
83              
84             return <
85            
86            
87            
88             {name}>
89             EOF
90 1         7 }
91              
92             sub request_suffix {
93 1     1 0 2 my ($self, $signature) = @_;
94 1         3 return <
95             \n
96             {name}>
97            
98            
99             EOF
100             }
101              
102             sub serialize {
103 12     12 0 32 my ($self, $arg, $d) = @_;
104              
105 12 50       69 if ( my $serializer = $self->can('serialize_'.$arg->{type}) ) {
106 12         31 return $serializer->( $self, $arg, $d );
107             }
108              
109 0         0 return _serialize_simple( $arg, $d );
110              
111 0         0 croak "Cannot find serializer for $arg->{type}";
112             }
113              
114             sub serialize_array {
115 1     1 0 5 return _serialize_array_or_vector( @_ );
116             }
117              
118             sub serialize_vector {
119 0     0 0 0 return _serialize_array_or_vector( @_ );
120             }
121              
122             sub serialize_map {
123 3     3 0 5 my ($self, $arg, $hash) = @_;
124              
125 3 50       7 if ( ref $hash ne 'HASH' ) {
126 0         0 croak "$arg->{key} is not HASH ref";
127             }
128              
129             #warn Dumper $hash;
130              
131 3 50 33     14 if ( ! exists $arg->{key_sig} && exists $arg->{key_type} ) {
132              
133 3         9 $arg->{key_sig} = {
134             type => $arg->{key_type},
135             key => 'key',
136             };
137             }
138              
139 3 100 66     19 if ( ! exists $arg->{value_sig} && exists $arg->{value_type} ) {
140              
141 2         5 $arg->{value_sig} = {
142             type => $arg->{value_type},
143             key => 'value',
144             };
145             }
146              
147 3 50       8 my $key_sig = $arg->{key_sig}
148             or croak "Unspecified key type for $arg->{key} map";
149 3 50       7 my $value_sig = $arg->{value_sig}
150             or croak "Unspecified key type for $arg->{key} map";
151              
152 3         2 my @output;
153              
154 3         7 push @output, _tag_start( $arg->{key}, q{xsi:type="apachesoap:Map"});
155              
156 3         11 while ( my ( $k, $v ) = each %$hash ) {
157 4         8 my @pair;
158              
159 4         3 push @pair, q{};
160 4         10 push @pair, $self->serialize(
161             $key_sig,
162             $k
163             );
164 4         9 push @pair, $self->serialize(
165             $value_sig,
166             $v
167             );
168 4         7 push @pair, q{};
169              
170 4         15 push @output, @pair;
171             }
172              
173 3         4 push @output, _tag_stop( $arg->{key} );
174              
175 3         14 return join '', @output;
176             }
177              
178             sub _serialize_array_or_vector {
179 1     1   3 my ($self, $arg, $array) = @_;
180              
181 1 50       4 if ( ref $array ne 'ARRAY' ) {
182 0         0 croak "$arg->{key} is not ARRAY ref";
183             }
184              
185 1 50 33     8 if ( ! exists $arg->{elem_sig} && exists $arg->{elem_type} ) {
186              
187 1         6 $arg->{elem_sig} = {
188             type => $arg->{elem_type},
189             key => 'item',
190             };
191             }
192              
193 1 50       5 my $elem_sig = $arg->{elem_sig}
194             or croak "Unspecified element type for $arg->{key} array";
195              
196 1         1 my @output;
197              
198 1         3 my $attr = q{xsi:type="apachesoap:Vector"};
199              
200 1 50       5 if ( $arg->{type} eq 'array' ) {
201 1         4 my $elem_type_xml = get_xml_type( $elem_sig->{type} );
202 1         3 my $length = scalar @$array;
203              
204 1         5 $attr =
205             q{xsi:type="SOAP-ENC:Array" }.
206             qq{SOAP-ENC:arrayType="$elem_type_xml\[$length]"};
207             }
208            
209 1         5 push @output, _tag_start( $arg->{key}, $attr );
210              
211             # my $fake_arg_signature = {
212             # key => 'item',
213             # type => $elem_type,
214             # };
215              
216 1         4 foreach my $elem (@$array) {
217 1         5 push @output, $self->serialize( $elem_sig, $elem );
218             }
219              
220 1         4 push @output, _tag_stop( $arg->{key} );
221              
222 1         7 return join '', @output;
223             }
224              
225             sub _serialize_simple {
226 8     8   11 my ($a, $d) = @_;
227              
228 8 50       15 croak "Undefined data for key $a->{key}\n" if not defined $d;
229              
230 8         9 my $t = eval { get_xml_type( $a->{type} ) };
  8         12  
231 8 50       14 $t or croak "Cannot simple serialize $t: $@";
232 8         31 return "<$a->{key} xsi:type=\"$t\">$d{key}>";
233             }
234              
235             sub _tag_start {
236 4     4   5 my ($tname, $attr) = @_;
237 4         15 return "<$tname $attr>";
238             }
239              
240             sub _tag_stop {
241 4     4   5 my ($tname) = @_;
242 4         8 return "";
243             }
244              
245             sub get_xml_type {
246 9     9 0 9 my $t = shift;
247              
248 9 50 100     65 return 'xsd:'.$t if ( $t eq 'int' or $t eq 'string' or $t eq 'boolean' );
      66        
249              
250 0         0 croak "Unknown type: $t";
251             }
252              
253             sub serialize_boolean {
254 1     1 0 2 my ($self, $arg, $d) = @_;
255              
256 1 50 33     27 if ( ! $d || $d =~ m/^false$/i ) {
    50 33        
257 0         0 $d = 'false';
258             }
259             elsif ( $d =~ m/^true$/i || $d ) {
260 1         3 $d = 'true';
261             }
262              
263 1         21 return _serialize_simple( $arg, $d );
264             }
265              
266             sub serialize_int {
267 3     3 0 4 my ($self, $arg, $d) = @_;
268              
269 3 50       13 if ( not $d =~ m/^[0-9]+$/ ) {
270 0         0 croak "$arg->{key} is not integer";
271             }
272              
273 3         5 return _serialize_simple( $arg, $d );
274             }
275              
276             sub serialize_string {
277 4     4 0 6 my ($self, $arg, $d) = @_;
278              
279 4         6 return _serialize_simple( $arg, escape_xml( $d ) );
280             }
281              
282             sub escape_xml {
283 4     4 0 5 $_ = shift;
284              
285 4 50       7 return $_ unless $_;
286              
287 4         8 s/&/&/xgs;
288 4         4 s/
289 4         4 s/>/>/xgs;
290 4         4 s/\"/"/xgs;
291              
292 4         11 return $_;
293             }
294              
295              
296              
297             1;