File Coverage

blib/lib/SOAP/WSDL/Base.pm
Criterion Covered Total %
statement 48 97 49.4
branch 13 40 32.5
condition n/a
subroutine 14 20 70.0
pod 0 8 0.0
total 75 165 45.4


line stmt bran cond sub pod time code
1             package SOAP::WSDL::Base;
2 11     11   565 use strict; use warnings;
  11     11   14  
  11         289  
  11         36  
  11         10  
  11         227  
3 11     11   479 use Class::Std::Fast::Storable;
  11         15569  
  11         46  
4 11     11   879 use List::Util;
  11         14  
  11         518  
5 11     11   47 use Scalar::Util;
  11         11  
  11         301  
6 11     11   49 use Carp qw(croak carp confess);
  11         13  
  11         3208  
7              
8             our $VERSION = 3.003;
9              
10             my %id_of :ATTR(:name :default<()>);
11             my %lang_of :ATTR(:name :default<()>);
12             my %name_of :ATTR(:name :default<()>);
13             my %namespace_of :ATTR(:name :default<()>);
14             my %documentation_of :ATTR(:name :default<()>);
15             my %annotation_of :ATTR(:name :default<()>);
16             my %targetNamespace_of :ATTR(:name :default<"">);
17             my %xmlns_of :ATTR(:name :default<{}>);
18             my %parent_of :ATTR(:get :default<()>);
19              
20             my %namespaces_of :ATTR(:default<{}>);
21              
22             sub namespaces {
23 0     0 0 0 return shift->get_xmlns();
24             }
25              
26             sub BUILD {
27 67     67 0 7509 my ($self, $ident, $arg_ref) = @_;
28 67 50       178 if (defined $arg_ref->{ parent }) {
29             $parent_of{ $ident } = delete $arg_ref->{ parent },
30 0         0 Scalar::Util::weaken($parent_of{ $ident });
31             }
32             }
33              
34             sub START {
35 67     67 0 22774 my ($self, $ident, $arg_ref) = @_;
36 67         103 $xmlns_of{ $ident }->{ 'xml' } = 'http://www.w3.org/XML/1998/namespace';
37 67         183 $namespaces_of{ $ident }->{ '#default' } = $self->get_xmlns()->{ '#default' };
38 67         271 $namespaces_of{ $ident }->{ 'xml' } = 'http://www.w3.org/XML/1998/namespace';
39             }
40              
41             #
42             # set_parent is hand-implemented to break up (weaken) the circular reference
43             # between an object and it's parent
44             #
45             sub set_parent {
46 0     0 0 0 $parent_of{ ${ $_[0]} } = $_[1];
  0         0  
47 0         0 Scalar::Util::weaken($parent_of{ ${ $_[0]} });
  0         0  
48             }
49              
50             # _accept is here to be called by visitor.
51             # The visitor pattern is a level of indirection - here the visitor calls
52             # $object->_accept($visitor) on each object, which in turn calls
53             # $visitor->visit_$class( $object ) where $class is the object's class.
54             #
55             sub _accept {
56 0     0   0 my $self = shift;
57 0         0 my $class = ref $self;
58 0         0 $class =~ s{ \A SOAP::WSDL:: }{}xms;
59 0         0 $class =~ s{ (:? :: ) }{_}gxms;
60 0         0 my $method = "visit_$class";
61 11     11   46 no strict qw(refs);
  11         14  
  11         1000  
62 0         0 return shift->$method( $self );
63             }
64              
65             # unfortunately, AUTOMETHOD is SLOW.
66             # Re-implement in derived package wherever speed is an issue...
67             #
68             sub AUTOMETHOD {
69 15     15 0 2219 my ($self, $ident, @values) = @_;
70 15         15 my $subname = $_; # Requested subroutine name is passed via $_
71              
72             # we're called as $self->push_something(@values);
73 15 100       56 if ($subname =~s{^push_}{}xms) {
    50          
    0          
74 7         9 my $getter = "get_$subname";
75 7         5 my $setter = "set_$subname";
76             # Checking here is paranoid - will fail fatally if there is no setter.
77             # And we would have to check getters, too.
78             # Maybe do it the Conway way via the Symbol table...
79             # ... can is way slow...
80             return sub {
81 11     11   40 no strict qw(refs);
  11         11  
  11         5661  
82 7     7   41 my $old_value = $self->$getter();
83             # Listify if not a list ref
84 7 100       31 $old_value = $old_value ? [ $old_value ] : [] if not ref $old_value;
    100          
85              
86 7         10 push @$old_value , @values;
87 7         16 $self->$setter( $old_value );
88 7         29 };
89             }
90              
91             # we're called as $obj->find_something($ns, $key)
92             elsif ($subname =~s {^find_}{get_}xms) {
93 8 100       17 @values = @{ $values[0] } if ref $values[0] eq 'ARRAY';
  1         18  
94             return sub {
95             return List::Util::first {
96 5 100       50 $_->get_targetNamespace() eq $values[0] &&
97             $_->get_name() eq $values[1]
98             }
99 8     8   34 @{ $self->$subname() };
  8         24  
100             }
101 8         29 }
102             elsif ($subname =~s {^first_}{get_}xms) {
103             return sub {
104 0     0   0 my $result_ref = $self->$subname();
105 0 0       0 return if not $result_ref;
106 0 0       0 return $result_ref if (not ref $result_ref eq 'ARRAY');
107 0         0 return $result_ref->[0];
108 0         0 };
109             }
110              
111 0         0 return;
112             }
113              
114             sub init {
115 0     0 0 0 my ($self, @args) = @_;
116 0         0 foreach my $value (@args) {
117 0 0       0 croak @args if (not defined ($value->{ Name }));
118              
119 0 0       0 if ($value->{ Name } =~m{^xmlns\:}xms) {
120             # add namespaces
121 0         0 $xmlns_of{ ident $self }->{ $value->{ LocalName } } = $value->{ Value };
122 0         0 next;
123             }
124              
125             # check for namespae-qualified attributes.
126             # neither XML Schema, nor WSDL1.1, nor the SOAP binding allow
127             # namespace-qualified attribute names
128 0         0 my ($ns, $localname) = split /\|/, $value->{ Name };
129 0 0       0 if ($ns) {
130 0         0 warn "found unrecognised attribute \{$ns}$localname (ignored)";
131 0         0 next;
132             }
133              
134 0         0 my $name = $value->{ LocalName };
135 0         0 my $method = "set_$name";
136 0         0 $self->$method( $value->{ Value } );
137             }
138 0         0 return $self;
139             }
140              
141             sub expand {
142 0     0 0 0 my ($self, $qname) = @_;
143 0         0 my $ns_of = $self->namespaces();
144 0         0 my $parent;
145 0 0       0 if (not $qname=~m{:}xm) {
146 0 0       0 if (defined $ns_of->{ '#default' }) {
147             # TODO check. Returning the targetNamespace for the default ns
148             # is probably wrong
149             #return $self->get_targetNamespace(), $qname;
150 0         0 return $ns_of->{ '#default' }, $qname;
151             }
152 0 0       0 if ($parent = $self->get_parent()) {
153 0         0 return $parent->expand($qname);
154             }
155 0         0 die "un-prefixed element name <$qname> found, but no default namespace set\n"
156             }
157              
158 0         0 my ($prefix, $localname) = split /:/x, $qname;
159              
160 0 0       0 return ($ns_of->{ $prefix }, $localname) if ($ns_of->{ $prefix });
161 0 0       0 if ($parent = $self->get_parent()) {
162 0         0 return $parent->expand($qname);
163             }
164 0         0 croak "unbound prefix $prefix found for $prefix:$localname. Bound prefixes are "
165 0         0 . join(', ', keys %{ $ns_of });
166             }
167             sub _expand;
168             *_expand = \&expand;
169              
170             sub schema {
171 1     1 0 3 my $parent = $_[0]->get_parent();
172 1 50       6 return if ! defined $parent;
173 0 0         return $parent if $parent->isa('SOAP::WSDL::XSD::Schema');
174 0           return $parent->schema();
175             }
176              
177             1;
178              
179             __END__