File Coverage

blib/lib/SOAP/WSDL/Base.pm
Criterion Covered Total %
statement 51 100 51.0
branch 13 40 32.5
condition n/a
subroutine 15 21 71.4
pod 0 8 0.0
total 79 169 46.7


line stmt bran cond sub pod time code
1             package SOAP::WSDL::Base;
2 11     11   207255 use strict; use warnings;
  11     11   27  
  11         438  
  11         64  
  11         22  
  11         340  
3 11     11   1999 use Class::Std::Fast::Storable;
  11         30171  
  11         84  
4 11     11   1402 use List::Util;
  11         21  
  11         838  
5 11     11   77 use Scalar::Util;
  11         22  
  11         592  
6 11     11   85 use Carp qw(croak carp confess);
  11         26  
  11         672  
7              
8 11     11   59 use version; our $VERSION = qv('3.001');
  11         27  
  11         87  
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 19738 my ($self, $ident, $arg_ref) = @_;
28 67 50       295 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 35034 my ($self, $ident, $arg_ref) = @_;
36 67         148 $xmlns_of{ $ident }->{ 'xml' } = 'http://www.w3.org/XML/1998/namespace';
37 67         278 $namespaces_of{ $ident }->{ '#default' } = $self->get_xmlns()->{ '#default' };
38 67         468 $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   5955 no strict qw(refs);
  11         22  
  11         1441  
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 4745 my ($self, $ident, @values) = @_;
70 15         23 my $subname = $_; # Requested subroutine name is passed via $_
71              
72             # we're called as $self->push_something(@values);
73 15 100       75 if ($subname =~s{^push_}{}xms) {
    50          
    0          
74 7         51 my $getter = "get_$subname";
75 7         12 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   60 no strict qw(refs);
  11         74  
  11         9950  
82 7     7   62 my $old_value = $self->$getter();
83             # Listify if not a list ref
84 7 100       51 $old_value = $old_value ? [ $old_value ] : [] if not ref $old_value;
    100          
85              
86 7         14 push @$old_value , @values;
87 7         26 $self->$setter( $old_value );
88 7         78 };
89             }
90              
91             # we're called as $obj->find_something($ns, $key)
92             elsif ($subname =~s {^find_}{get_}xms) {
93 8 100       25 @values = @{ $values[0] } if ref $values[0] eq 'ARRAY';
  1         3  
94             return sub {
95             return List::Util::first {
96 5 100       69 $_->get_targetNamespace() eq $values[0] &&
97             $_->get_name() eq $values[1]
98             }
99 8     8   81 @{ $self->$subname() };
  8         51  
100             }
101 8         39 }
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 9 my $parent = $_[0]->get_parent();
172 1 50       9 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__