File Coverage

lib/Google/Ads/SOAP/Generator/TypemapVisitor.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             # Copyright 2012, Google Inc. All Rights Reserved.
2             #
3             # Licensed under the Apache License, Version 2.0 (the "License");
4             # you may not use this file except in compliance with the License.
5             # You may obtain a copy of the License at
6             #
7             # http://www.apache.org/licenses/LICENSE-2.0
8             #
9             # Unless required by applicable law or agreed to in writing, software
10             # distributed under the License is distributed on an "AS IS" BASIS,
11             # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12             # See the License for the specific language governing permissions and
13             # limitations under the License.
14             #
15             # Custom visitor for generation of typemaps based on
16             # SOAP::WSDL::Generator::Visitor::Typemap, with some overriden methods via
17             # inheritance.
18              
19             package Google::Ads::SOAP::Generator::TypemapVisitor;
20              
21 2     2   2474 use strict;
  2         3  
  2         57  
22 2     2   8 use warnings;
  2         5  
  2         56  
23 2     2   9 use base qw(SOAP::WSDL::Generator::Visitor::Typemap);
  2         3  
  2         329  
24              
25 2     2   3012 use Class::Std::Fast::Storable;
  2         4  
  2         11  
26              
27             sub set_typemap_entry {
28             my ($self, $value) = @_;
29             my $path = join(q{/}, @{$self->get_path()});
30             my $tm = $self->get_typemap();
31             if ($tm->{$path} && $path =~ m/Fault\/detail\/ApiExceptionFault/) {
32             return;
33             }
34             $tm->{$path} = $value;
35             }
36              
37             sub visit_XSD_Element {
38             my ($self, $ident, $element) = ($_[0], ident $_[0], $_[1]);
39              
40             my @path = @{$self->get_path()};
41             my $path = join '/', @path;
42             my $parent = $self->get_typemap()->{$path};
43              
44             # PATCH breaking cycles
45             if (scalar(@path) > 30) {
46             return;
47             }
48             # END PATCH
49              
50             $self->SUPER::visit_XSD_Element($_[1]);
51             }
52              
53             sub visit_XSD_ComplexType {
54             my ($self, $ident, $type) = ($_[0], ident $_[0], $_[1]);
55              
56             my $variety = $type->get_variety();
57             my $derivation = $type->get_derivation();
58             my $content_model = $type->get_contentModel();
59              
60             return if not $variety or ($content_model eq "simpleContent");
61             if (grep { $_ eq $variety } qw(all sequence choice)) {
62             # Recursively going to visit child element since the type variety is
63             # either all sequence choice.
64             if (my $type_name = $type->get_base()) {
65             my $subtype =
66             $self->get_definitions()->first_types()
67             ->find_type($type->expand($type_name));
68             for (@{$subtype->get_element() || []}) {
69             $_->_accept($self);
70             }
71             }
72              
73             for (@{$type->get_element() || []}) {
74             $_->_accept($self);
75             }
76             }
77              
78             # PATCH - We need to also check if the complex type has derivations and
79             # include type path for all the types that derived from it.
80             my $last_path_elem = pop(@{$self->get_path()});
81             my $def_types = $self->get_definitions()->first_types();
82             my $schema = @{$def_types->get_schema()}[1];
83             my @types = @{$schema->get_type()};
84             my $base_type = $type->get_name();
85              
86             if ( @{$self->get_path()}[0]
87             && @{$self->get_path()}[0] eq "ApiExceptionFault")
88             {
89             @{$self->get_path()}[0] = "Fault/detail/ApiExceptionFault";
90             }
91              
92             if (defined $base_type) {
93             my $schemas = @{$self->get_definitions()->get_types()}[0]->get_schema;
94             SCHEMA: foreach my $my_schema (@{$schemas}) {
95             next SCHEMA if ($my_schema->isa("SOAP::WSDL::XSD::Schema::Builtin"));
96             my @types = @{$my_schema->get_type()};
97             TYPE: foreach my $type (@types) {
98             if ($type->isa("SOAP::WSDL::XSD::ComplexType")) {
99             my $type_name = $type->get_name();
100             my $base = $type->get_base();
101             next TYPE if !$base;
102             $base =~ s{ .*: }{}xms;
103             if ($base eq $base_type) {
104             # Checking for infinite cycles if the type has already been mapped
105             # before we skip to the next one.
106             foreach my $path_elem (@{$self->get_path()}) {
107             next TYPE if $path_elem eq $last_path_elem . "[$type_name]";
108             }
109              
110             # In this case we generate a new path that includes the type name
111             # E.G. /elem1/elem2[type]
112             if ($last_path_elem =~ m/\[[^\]]+\]/) {
113             $last_path_elem =~ s/\[[^\]]+\]/[${type_name}]/;
114             push(@{$self->get_path()}, $last_path_elem);
115             } else {
116             push(@{$self->get_path()}, $last_path_elem . "[$type_name]");
117             }
118             my $typeclass = $self->get_resolver()->create_xsd_name($type);
119              
120             # Setting current typemap class before to allow it to be used from
121             # inside _accept.
122             $self->set_typemap_entry($typeclass);
123             $type->_accept($self);
124              
125             # Setting it afterwards again since accept could have touch it.
126             $self->set_typemap_entry($typeclass);
127             pop(@{$self->get_path()});
128             }
129             }
130             }
131             }
132             }
133             push(@{$self->get_path()}, $last_path_elem);
134             # END OF PATCH.
135              
136             return if (!$derivation);
137              
138             if ($derivation eq "restriction") {
139             # Resolving the base, getting atomic type and runnning on elements.
140             if (my $type_name = $type->get_base()) {
141             my $subtype =
142             $self->get_definitions()->first_types()
143             ->find_type($type->expand($type_name));
144             for (@{$subtype->get_element() || []}) {
145             $_->_accept($self);
146             }
147             }
148             } elsif ($derivation eq "extension") {
149             # Resolving the base, getting atomic type and runnning on elements.
150             while (my $type_name = $type->get_base()) {
151             $type =
152             $self->get_definitions()->first_types()
153             ->find_type($type->expand($type_name));
154             for (@{$type->get_element() || []}) {
155             $_->_accept($self);
156             }
157             }
158             }
159             }
160              
161             return 1;