| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#!/usr/bin/perl |
|
2
|
|
|
|
|
|
|
package SOAP::WSDL::XSD::Typelib::ComplexType; |
|
3
|
12
|
|
|
12
|
|
370229
|
use strict; |
|
|
12
|
|
|
|
|
31
|
|
|
|
12
|
|
|
|
|
609
|
|
|
4
|
12
|
|
|
12
|
|
66
|
use warnings; |
|
|
12
|
|
|
|
|
23
|
|
|
|
12
|
|
|
|
|
404
|
|
|
5
|
12
|
|
|
12
|
|
61
|
use Carp; |
|
|
12
|
|
|
|
|
18
|
|
|
|
12
|
|
|
|
|
864
|
|
|
6
|
12
|
|
|
12
|
|
13296
|
use SOAP::WSDL::XSD::Typelib::Builtin; |
|
|
12
|
|
|
|
|
39
|
|
|
|
12
|
|
|
|
|
424
|
|
|
7
|
12
|
|
|
12
|
|
71
|
use Scalar::Util qw(blessed); |
|
|
12
|
|
|
|
|
24
|
|
|
|
12
|
|
|
|
|
1028
|
|
|
8
|
12
|
|
|
12
|
|
15492
|
use Data::Dumper; |
|
|
12
|
|
|
|
|
673260
|
|
|
|
12
|
|
|
|
|
1189
|
|
|
9
|
|
|
|
|
|
|
require Class::Std::Fast::Storable; |
|
10
|
12
|
|
|
12
|
|
47114
|
use Class::Load (); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
use base qw(SOAP::WSDL::XSD::Typelib::Builtin::anyType); |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use version; our $VERSION = qv('3.001'); |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
# remove in 2.1 |
|
17
|
|
|
|
|
|
|
our $AS_HASH_REF_WITHOUT_ATTRIBUTES = 0; |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my %ELEMENT_FORM_QUALIFIED_OF; # denotes whether elements are qualified |
|
20
|
|
|
|
|
|
|
my %ELEMENTS_FROM; # order of elements in a class |
|
21
|
|
|
|
|
|
|
my %ATTRIBUTES_OF; # references to value hashes |
|
22
|
|
|
|
|
|
|
my %CLASSES_OF; # class names of elements in a class |
|
23
|
|
|
|
|
|
|
my %NAMES_OF; # XML names of elements in a class |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# XML Attribute handling |
|
27
|
|
|
|
|
|
|
my %xml_attr_of :ATTR(); |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
# Namespace handling |
|
30
|
|
|
|
|
|
|
my %xmlns_of :ATTR(); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# don't you ever dare to use this ! |
|
33
|
|
|
|
|
|
|
our $___attributes_of_ref = \%ATTRIBUTES_OF; |
|
34
|
|
|
|
|
|
|
our $___xml_attribute_of_ref = \%xml_attr_of; |
|
35
|
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
# STORABLE_ methods for supporting Class::Std::Fast::Storable. |
|
37
|
|
|
|
|
|
|
# We could also handle them via AUTOMETHOD, |
|
38
|
|
|
|
|
|
|
# but AUTOMETHOD should always croak... |
|
39
|
|
|
|
|
|
|
# Actually, AUTOMETHOD is faster (~1%) if Class::Std::Fast is loaded |
|
40
|
|
|
|
|
|
|
# properly, and slower (~10%) if not. |
|
41
|
|
|
|
|
|
|
# Hmmm. Trade 1% for 10? |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
my %STORABLE_METHODS = ( |
|
44
|
|
|
|
|
|
|
STORABLE_freeze_pre => undef, |
|
45
|
|
|
|
|
|
|
STORABLE_freeze_post => undef, |
|
46
|
|
|
|
|
|
|
STORABLE_thaw_pre => undef, |
|
47
|
|
|
|
|
|
|
STORABLE_thaw_post => undef, |
|
48
|
|
|
|
|
|
|
); |
|
49
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
# for error reporting. Eases working with data objects... |
|
51
|
|
|
|
|
|
|
sub AUTOMETHOD { |
|
52
|
|
|
|
|
|
|
# return before unpacking @_ for speed reasons |
|
53
|
|
|
|
|
|
|
return if exists $STORABLE_METHODS{$_}; |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my ($self, $ident, @args_from) = @_; |
|
56
|
|
|
|
|
|
|
my $class = ref $self || $self or die "Cannot call AUTOMETHOD as function"; |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
# Test whether we're called from ->can() |
|
59
|
|
|
|
|
|
|
my @caller = caller(1); |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# return if not called by AUTOLOAD - caller must be something like can() |
|
62
|
|
|
|
|
|
|
# Unfortunately we cannot test for "UNIVERSAL::can", as it gets overwritten |
|
63
|
|
|
|
|
|
|
# by both Class::Std and Class::Std::Fast, and we don't know the loading |
|
64
|
|
|
|
|
|
|
# order (Class::Std::Fast should be loaded before for maximum speedup) |
|
65
|
|
|
|
|
|
|
return if $caller[3] ne 'Class::Std::AUTOLOAD'; |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
confess "Can't locate object method \"$_\" via package \"$class\". \n" |
|
68
|
|
|
|
|
|
|
. "Valid methods are: " |
|
69
|
|
|
|
|
|
|
. join(', ', map { ("get_$_" , "set_$_") } keys %{ $ATTRIBUTES_OF{ $class } }) |
|
70
|
|
|
|
|
|
|
. "\n" |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub attr { |
|
74
|
|
|
|
|
|
|
# We're working on @_ for speed. |
|
75
|
|
|
|
|
|
|
# Normally, the first line would look like this: |
|
76
|
|
|
|
|
|
|
# my $self = shift; |
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
my $class = $_[0]->__get_attr_class() |
|
79
|
|
|
|
|
|
|
or return; |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# pass arguments to attributes constructor (if any); |
|
82
|
|
|
|
|
|
|
# lets attr($foo) work as setter |
|
83
|
|
|
|
|
|
|
if ($_[1]) { |
|
84
|
|
|
|
|
|
|
return $xml_attr_of{ ${$_[0]} } = $class->new($_[1]); |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
return $xml_attr_of{ ${$_[0]} } if exists $xml_attr_of{ ${$_[0]} }; |
|
87
|
|
|
|
|
|
|
return $xml_attr_of{ ${$_[0]} } = $class->new(); |
|
88
|
|
|
|
|
|
|
} |
|
89
|
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub serialize_attr { |
|
91
|
|
|
|
|
|
|
return q{} if not $xml_attr_of{ ${ $_[0] } }; |
|
92
|
|
|
|
|
|
|
return $xml_attr_of{ ${ $_[0] } }->serialize(); |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
# TODO: are complextypes are always true ? |
|
96
|
|
|
|
|
|
|
sub as_bool :BOOLIFY { 1 } |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
sub as_hash_ref { |
|
99
|
|
|
|
|
|
|
# we're working on $_[0] for speed (as always...) |
|
100
|
|
|
|
|
|
|
# |
|
101
|
|
|
|
|
|
|
# Normally the first line would read: |
|
102
|
|
|
|
|
|
|
# my ($self, $ignore_attributes) = @_; |
|
103
|
|
|
|
|
|
|
# |
|
104
|
|
|
|
|
|
|
my $attributes_ref = $ATTRIBUTES_OF{ ref $_[0] }; |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
my $hash_of_ref = {}; |
|
107
|
|
|
|
|
|
|
if ($_[0]->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType')) { |
|
108
|
|
|
|
|
|
|
$hash_of_ref->{ value } = $_[0]->get_value(); |
|
109
|
|
|
|
|
|
|
} |
|
110
|
|
|
|
|
|
|
else { |
|
111
|
|
|
|
|
|
|
foreach my $attribute (keys %{ $attributes_ref }) { |
|
112
|
|
|
|
|
|
|
next if not defined $attributes_ref->{ $attribute }->{ ${ $_[0] } }; |
|
113
|
|
|
|
|
|
|
my $value = $attributes_ref->{ $attribute }->{ ${ $_[0] } }; |
|
114
|
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
$hash_of_ref->{ $attribute } = blessed $value |
|
116
|
|
|
|
|
|
|
? $value->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') |
|
117
|
|
|
|
|
|
|
? $value->get_value() |
|
118
|
|
|
|
|
|
|
: $value->as_hash_ref($_[1]) |
|
119
|
|
|
|
|
|
|
: ref $value eq 'ARRAY' |
|
120
|
|
|
|
|
|
|
? [ |
|
121
|
|
|
|
|
|
|
map { |
|
122
|
|
|
|
|
|
|
$_->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') |
|
123
|
|
|
|
|
|
|
? $_->get_value() |
|
124
|
|
|
|
|
|
|
: $_->as_hash_ref($_[1]) |
|
125
|
|
|
|
|
|
|
} @{ $value } |
|
126
|
|
|
|
|
|
|
] |
|
127
|
|
|
|
|
|
|
: die "Neither blessed obj nor list ref"; |
|
128
|
|
|
|
|
|
|
}; |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
# $AS_HASH_REF_WITHOUT_ATTRIBUTES is deprecated by NOW and will be removed |
|
132
|
|
|
|
|
|
|
# in 2.1 |
|
133
|
|
|
|
|
|
|
return $hash_of_ref if $_[1] or $AS_HASH_REF_WITHOUT_ATTRIBUTES; |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
if (exists $xml_attr_of{ ${ $_[0] } }) { |
|
137
|
|
|
|
|
|
|
$hash_of_ref->{ xmlattr } = $xml_attr_of{ ${ $_[0] } }->as_hash_ref(); |
|
138
|
|
|
|
|
|
|
} |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
return $hash_of_ref; |
|
141
|
|
|
|
|
|
|
} |
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# we store per-class elements. |
|
144
|
|
|
|
|
|
|
# call as __PACKAGE__->_factory |
|
145
|
|
|
|
|
|
|
sub _factory { |
|
146
|
|
|
|
|
|
|
my $class = shift; |
|
147
|
|
|
|
|
|
|
$ELEMENTS_FROM{ $class } = shift; |
|
148
|
|
|
|
|
|
|
$ATTRIBUTES_OF{ $class } = shift; |
|
149
|
|
|
|
|
|
|
$CLASSES_OF{ $class } = shift; |
|
150
|
|
|
|
|
|
|
$NAMES_OF{ $class } = shift; |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
no strict qw(refs); |
|
153
|
|
|
|
|
|
|
no warnings qw(redefine); |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
while (my ($name, $attribute_ref) = each %{ $ATTRIBUTES_OF{ $class } } ) { |
|
156
|
|
|
|
|
|
|
my $type = $CLASSES_OF{ $class }->{ $name } |
|
157
|
|
|
|
|
|
|
or croak "No class given for $name"; |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# require all types here |
|
160
|
|
|
|
|
|
|
Class::Load::is_class_loaded($type) |
|
161
|
|
|
|
|
|
|
or eval { Class::Load::load_class $type } |
|
162
|
|
|
|
|
|
|
or croak $@; |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# check now, so we don't need to do it later. |
|
165
|
|
|
|
|
|
|
# $is_list is used in the methods created. Filling it now means |
|
166
|
|
|
|
|
|
|
# we don't have to check it every time the method is called, but |
|
167
|
|
|
|
|
|
|
# can just use $is_list, which will hold the value assigned to |
|
168
|
|
|
|
|
|
|
# it when the method was created. |
|
169
|
|
|
|
|
|
|
my $is_list = $type->isa('SOAP::WSDL::XSD::Typelib::Builtin::list'); |
|
170
|
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# The set_$name method below looks rather weird, |
|
172
|
|
|
|
|
|
|
# but is optimized for performance. |
|
173
|
|
|
|
|
|
|
# |
|
174
|
|
|
|
|
|
|
# We could use sub calls for sure, but these are much slower. And |
|
175
|
|
|
|
|
|
|
# the logic is not that easy: |
|
176
|
|
|
|
|
|
|
# |
|
177
|
|
|
|
|
|
|
# we accept: |
|
178
|
|
|
|
|
|
|
# a) objects |
|
179
|
|
|
|
|
|
|
# b) scalars |
|
180
|
|
|
|
|
|
|
# c) list refs |
|
181
|
|
|
|
|
|
|
# d) hash refs |
|
182
|
|
|
|
|
|
|
# e) mixed stuff of all of the above, so we have to set our child to |
|
183
|
|
|
|
|
|
|
# a) value if it's an object |
|
184
|
|
|
|
|
|
|
# b) New object of expected class with value for simple values |
|
185
|
|
|
|
|
|
|
# c 1) New object with value for list values and list type |
|
186
|
|
|
|
|
|
|
# c 2) List ref of new objects with value for list values and |
|
187
|
|
|
|
|
|
|
# non-list type |
|
188
|
|
|
|
|
|
|
# c + e 1) List ref of objects for list values (list of objects) |
|
189
|
|
|
|
|
|
|
# and non-list type |
|
190
|
|
|
|
|
|
|
# c + e 2) List ref of new objects for list values (list of hashes) |
|
191
|
|
|
|
|
|
|
# and non-list type where the hash ref is passed to new as |
|
192
|
|
|
|
|
|
|
# argument |
|
193
|
|
|
|
|
|
|
# d) New object with values passed to new for HASH references |
|
194
|
|
|
|
|
|
|
# |
|
195
|
|
|
|
|
|
|
# We throw an error on |
|
196
|
|
|
|
|
|
|
# a) list refs of list refs - don't know what to do with this (maybe |
|
197
|
|
|
|
|
|
|
# use for lists of list types ?) |
|
198
|
|
|
|
|
|
|
# b) wrong object types |
|
199
|
|
|
|
|
|
|
# c) non-blessed non-ARRAY/HASH references - if you can define semantics |
|
200
|
|
|
|
|
|
|
# for GLOB or SCALAR references, feel free to add them. |
|
201
|
|
|
|
|
|
|
# d) we should also die for non-blessed non-ARRAY/HASH references in |
|
202
|
|
|
|
|
|
|
# lists but don't do yet - oh my ! |
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
# keep in sync with Generator::Template::Plugin::XSD - maybe use |
|
205
|
|
|
|
|
|
|
# function to allow substituting via symbol table... |
|
206
|
|
|
|
|
|
|
my $method_name = $name; |
|
207
|
|
|
|
|
|
|
$method_name =~s{[\.\-]}{_}xmsg; |
|
208
|
|
|
|
|
|
|
*{ "$class\::set_$method_name" } = sub { |
|
209
|
|
|
|
|
|
|
if (not $#_) { |
|
210
|
|
|
|
|
|
|
delete $attribute_ref->{ ${ $_[0] } }; |
|
211
|
|
|
|
|
|
|
return; |
|
212
|
|
|
|
|
|
|
}; |
|
213
|
|
|
|
|
|
|
my $is_ref = ref $_[1]; |
|
214
|
|
|
|
|
|
|
$attribute_ref->{ ${ $_[0] } } = ($is_ref) |
|
215
|
|
|
|
|
|
|
? ($is_ref eq 'ARRAY') |
|
216
|
|
|
|
|
|
|
? $is_list # remembered from outside closure |
|
217
|
|
|
|
|
|
|
? $type->new({ value => $_[1] }) # it's a list element - can take list ref as value |
|
218
|
|
|
|
|
|
|
: [ map { # it's not a list element - set value to list of objects |
|
219
|
|
|
|
|
|
|
ref $_ |
|
220
|
|
|
|
|
|
|
? ref $_ eq 'HASH' |
|
221
|
|
|
|
|
|
|
? $type->new($_) |
|
222
|
|
|
|
|
|
|
: ref $_ eq $type |
|
223
|
|
|
|
|
|
|
? $_ |
|
224
|
|
|
|
|
|
|
: croak "cannot use " . ref($_) . " reference as value for $name - $type required" |
|
225
|
|
|
|
|
|
|
: $type->new({ value => $_ }) |
|
226
|
|
|
|
|
|
|
} @{ $_[1] } |
|
227
|
|
|
|
|
|
|
] |
|
228
|
|
|
|
|
|
|
: $is_ref eq 'HASH' |
|
229
|
|
|
|
|
|
|
? $type->new( $_[1] ) |
|
230
|
|
|
|
|
|
|
# neither ARRAY nor HASH - probably an object... - |
|
231
|
|
|
|
|
|
|
# do we need to test for it being blessed? |
|
232
|
|
|
|
|
|
|
: blessed $_[1] && $_[1]->isa($type) # of required type ? |
|
233
|
|
|
|
|
|
|
? $_[1] # use it |
|
234
|
|
|
|
|
|
|
: die croak "cannot use $is_ref reference as value for $name - $type required" |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# not $is_ref |
|
237
|
|
|
|
|
|
|
: defined $_[1] ? $type->new({ value => $_[1] }) : () ; |
|
238
|
|
|
|
|
|
|
return; |
|
239
|
|
|
|
|
|
|
}; |
|
240
|
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
*{ "$class\::add_$method_name" } = sub { |
|
242
|
|
|
|
|
|
|
warn "attempting to add empty value to " . ref $_[0] |
|
243
|
|
|
|
|
|
|
if not defined $_[1]; |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
# first call |
|
246
|
|
|
|
|
|
|
# test for existance, not for definedness |
|
247
|
|
|
|
|
|
|
if (not exists $attribute_ref->{ ${ $_[0]} }) { |
|
248
|
|
|
|
|
|
|
$attribute_ref->{ ${ $_[0]} } = $_[1]; |
|
249
|
|
|
|
|
|
|
return; |
|
250
|
|
|
|
|
|
|
} |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
if (not ref $attribute_ref->{ ${ $_[0]} } eq 'ARRAY') { |
|
253
|
|
|
|
|
|
|
# second call: listify previous value if it's no list and add current |
|
254
|
|
|
|
|
|
|
$attribute_ref->{ ${ $_[0]} } = [ $attribute_ref->{ ${ $_[0]} }, $_[1] ]; |
|
255
|
|
|
|
|
|
|
return; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# second and following: add to list |
|
259
|
|
|
|
|
|
|
push @{ $attribute_ref->{ ${ $_[0]} } }, $_[1]; |
|
260
|
|
|
|
|
|
|
return; |
|
261
|
|
|
|
|
|
|
}; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# TODO Could be moved as normal method into base class, e.g. here. |
|
265
|
|
|
|
|
|
|
# Hmm. let's see... |
|
266
|
|
|
|
|
|
|
*{ "$class\::new" } = sub { |
|
267
|
|
|
|
|
|
|
# We're working on @_ for speed. |
|
268
|
|
|
|
|
|
|
# Normally, the first line would look like this: |
|
269
|
|
|
|
|
|
|
# my ($class, $args_of) = @_; |
|
270
|
|
|
|
|
|
|
# |
|
271
|
|
|
|
|
|
|
# The hanging side comment show you what would be there, then. |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
# Read as: |
|
274
|
|
|
|
|
|
|
# my $self = bless \(my $o = Class::Std::Fast::ID()), $class; |
|
275
|
|
|
|
|
|
|
my $self = bless \(my $o = Class::Std::Fast::ID()), $_[0]; |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
# Set attributes if passed via { xmlattr => \%attributes } |
|
278
|
|
|
|
|
|
|
# |
|
279
|
|
|
|
|
|
|
# This works just because |
|
280
|
|
|
|
|
|
|
# a) xmlattr cannot be used as valid XML identifier (it starts |
|
281
|
|
|
|
|
|
|
# with "xml" which is banned by the XML schema standard) |
|
282
|
|
|
|
|
|
|
# b) $o->attr($attribute_ref) passes $attribute_ref to the |
|
283
|
|
|
|
|
|
|
# attribute object's constructor |
|
284
|
|
|
|
|
|
|
# c) we are in the object's constructor here (which means that) |
|
285
|
|
|
|
|
|
|
# no attributes object can have been legally constructed |
|
286
|
|
|
|
|
|
|
# before. |
|
287
|
|
|
|
|
|
|
if (exists $_[1]->{xmlattr}) { # $args_of->{xmlattr} |
|
288
|
|
|
|
|
|
|
$self->attr(delete $_[1]->{xmlattr}); |
|
289
|
|
|
|
|
|
|
} |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
# iterate over keys of arguments |
|
292
|
|
|
|
|
|
|
# and call set appropriate field in clase |
|
293
|
|
|
|
|
|
|
map { ($ATTRIBUTES_OF{ $class }->{ $_ }) |
|
294
|
|
|
|
|
|
|
? do { |
|
295
|
|
|
|
|
|
|
my $method = "set_$_"; |
|
296
|
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
# keep in sync with Generator::Template::Plugin::XSD - maybe use |
|
298
|
|
|
|
|
|
|
# function to allow substituting via symbol table... |
|
299
|
|
|
|
|
|
|
$method =~s{[\.\-]}{_}xmsg; |
|
300
|
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
$self->$method( $_[1]->{ $_ } ); # ( $args_of->{ $_ } ); |
|
302
|
|
|
|
|
|
|
} |
|
303
|
|
|
|
|
|
|
: $_ =~ m{ \A # beginning of string |
|
304
|
|
|
|
|
|
|
xmlns # xmlns |
|
305
|
|
|
|
|
|
|
}xms # get_elements is inlined for performance. |
|
306
|
|
|
|
|
|
|
? () |
|
307
|
|
|
|
|
|
|
: do { |
|
308
|
|
|
|
|
|
|
croak "unknown field $_ in $class. Valid fields are:\n" |
|
309
|
|
|
|
|
|
|
. join(', ', @{ $ELEMENTS_FROM{ $class } }) . "\n" |
|
310
|
|
|
|
|
|
|
. "Structure given:\n" . Dumper @_ }; |
|
311
|
|
|
|
|
|
|
} keys %{ $_[1] }; # %$args_of; |
|
312
|
|
|
|
|
|
|
return $self; |
|
313
|
|
|
|
|
|
|
}; |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
# this _serialize method works fine for and |
|
316
|
|
|
|
|
|
|
# complextypes, as well as for or |
|
317
|
|
|
|
|
|
|
# , and attribute sets. |
|
318
|
|
|
|
|
|
|
# |
|
319
|
|
|
|
|
|
|
# But what about choice, extension ? |
|
320
|
|
|
|
|
|
|
# |
|
321
|
|
|
|
|
|
|
# Triggers XML attribute serialization if the options hash ref contains |
|
322
|
|
|
|
|
|
|
# a attr element with a true value. |
|
323
|
|
|
|
|
|
|
*{ "$class\::_serialize" } = sub { |
|
324
|
|
|
|
|
|
|
my $ident = ${ $_[0] }; |
|
325
|
|
|
|
|
|
|
my $option_ref = $_[1]; |
|
326
|
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
# return concatenated return value of serialize call of all |
|
328
|
|
|
|
|
|
|
# elements retrieved from get_elements expanding list refs. |
|
329
|
|
|
|
|
|
|
return \join q{} , map { |
|
330
|
|
|
|
|
|
|
my $element = $ATTRIBUTES_OF{ $class }->{ $_ }->{ $ident }; |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# do we have some content |
|
333
|
|
|
|
|
|
|
if (defined $element) { |
|
334
|
|
|
|
|
|
|
$element = [ $element ] if not ref $element eq 'ARRAY'; |
|
335
|
|
|
|
|
|
|
# use || $_; for backward compatibility |
|
336
|
|
|
|
|
|
|
my $name = $NAMES_OF{$class}->{$_} || $_; |
|
337
|
|
|
|
|
|
|
my $target_namespace = $_[0]->get_xmlns(); |
|
338
|
|
|
|
|
|
|
map { |
|
339
|
|
|
|
|
|
|
# serialize element elements with their own serializer |
|
340
|
|
|
|
|
|
|
# but name them like they're named here. |
|
341
|
|
|
|
|
|
|
# TODO: check. element ref="" has a name??? |
|
342
|
|
|
|
|
|
|
if ( $_->isa( 'SOAP::WSDL::XSD::Typelib::Element' ) ) { |
|
343
|
|
|
|
|
|
|
# serialize elements of different namespaces |
|
344
|
|
|
|
|
|
|
# with namespace declaration |
|
345
|
|
|
|
|
|
|
($target_namespace ne $_->get_xmlns()) |
|
346
|
|
|
|
|
|
|
? $_->serialize({ name => $name, qualified => 1 }) |
|
347
|
|
|
|
|
|
|
: $_->serialize({ name => $name }); |
|
348
|
|
|
|
|
|
|
} |
|
349
|
|
|
|
|
|
|
# serialize complextype elments (of other types) with their |
|
350
|
|
|
|
|
|
|
# serializer, but add element tags around. |
|
351
|
|
|
|
|
|
|
else { |
|
352
|
|
|
|
|
|
|
# default for undef is true |
|
353
|
|
|
|
|
|
|
if (! defined $ELEMENT_FORM_QUALIFIED_OF{ $class } |
|
354
|
|
|
|
|
|
|
or $ELEMENT_FORM_QUALIFIED_OF{ $class } |
|
355
|
|
|
|
|
|
|
) { |
|
356
|
|
|
|
|
|
|
# handle types from different namespaces |
|
357
|
|
|
|
|
|
|
# |
|
358
|
|
|
|
|
|
|
# serialize with last namespace put on stack |
|
359
|
|
|
|
|
|
|
# if the last namespace is a change from the |
|
360
|
|
|
|
|
|
|
# before-last |
|
361
|
|
|
|
|
|
|
# |
|
362
|
|
|
|
|
|
|
if ( |
|
363
|
|
|
|
|
|
|
exists $option_ref->{ xmlns_stack } |
|
364
|
|
|
|
|
|
|
&& (scalar @{ $option_ref->{ xmlns_stack } } >= 2) |
|
365
|
|
|
|
|
|
|
&& ($option_ref->{ xmlns_stack }->[-1] ne $option_ref->{ xmlns_stack }->[-2])) { |
|
366
|
|
|
|
|
|
|
# warn "New namespace: ", $option_ref->{ xmlns_stack }->[-1]; |
|
367
|
|
|
|
|
|
|
join q{}, $_->start_tag({ name => $name , |
|
368
|
|
|
|
|
|
|
xmlns => $option_ref->{ xmlns_stack }->[-1], |
|
369
|
|
|
|
|
|
|
%{ $option_ref } }) |
|
370
|
|
|
|
|
|
|
, $_->serialize($option_ref) |
|
371
|
|
|
|
|
|
|
, $_->end_tag({ name => $name , %{ $option_ref } }); |
|
372
|
|
|
|
|
|
|
} |
|
373
|
|
|
|
|
|
|
else { |
|
374
|
|
|
|
|
|
|
join q{}, $_->start_tag({ name => $name , %{ $option_ref } }) |
|
375
|
|
|
|
|
|
|
, $_->serialize($option_ref) |
|
376
|
|
|
|
|
|
|
, $_->end_tag({ name => $name , %{ $option_ref } }); |
|
377
|
|
|
|
|
|
|
} |
|
378
|
|
|
|
|
|
|
} |
|
379
|
|
|
|
|
|
|
else { |
|
380
|
|
|
|
|
|
|
# in elementFormDefault="unqualified" mode, |
|
381
|
|
|
|
|
|
|
# the serialize method has to set |
|
382
|
|
|
|
|
|
|
# xmnlns="" on all elements inside a ComplexType |
|
383
|
|
|
|
|
|
|
# |
|
384
|
|
|
|
|
|
|
# Other serializers usually use prefixes |
|
385
|
|
|
|
|
|
|
# for "unqualified" and just omit all prefixes |
|
386
|
|
|
|
|
|
|
# for inner elements |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# check whether we "had" a xmlns around |
|
389
|
|
|
|
|
|
|
my $set_xmlns = delete $option_ref->{xmlns}; |
|
390
|
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
# serialize start tag with xmlns="" if out parent |
|
392
|
|
|
|
|
|
|
# did not do that |
|
393
|
|
|
|
|
|
|
join q{}, $_->start_tag({ |
|
394
|
|
|
|
|
|
|
name => $name, |
|
395
|
|
|
|
|
|
|
%{ $option_ref }, |
|
396
|
|
|
|
|
|
|
(! defined $set_xmlns) |
|
397
|
|
|
|
|
|
|
? (xmlns => "") |
|
398
|
|
|
|
|
|
|
: () |
|
399
|
|
|
|
|
|
|
}) |
|
400
|
|
|
|
|
|
|
# add xmlns = "" to child serialize options |
|
401
|
|
|
|
|
|
|
# to avoid putting xmlns="" everywhere |
|
402
|
|
|
|
|
|
|
, $_->serialize({ %{$option_ref}, xmlns => "" }) |
|
403
|
|
|
|
|
|
|
, $_->end_tag({ name => $name , %{ $option_ref } }); |
|
404
|
|
|
|
|
|
|
} |
|
405
|
|
|
|
|
|
|
} |
|
406
|
|
|
|
|
|
|
} @{ $element } |
|
407
|
|
|
|
|
|
|
} |
|
408
|
|
|
|
|
|
|
else { |
|
409
|
|
|
|
|
|
|
q{}; |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
} (@{ $ELEMENTS_FROM{ $class } }); |
|
412
|
|
|
|
|
|
|
}; |
|
413
|
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
# put hidden complex serializer into class |
|
415
|
|
|
|
|
|
|
# ... but not for AttributeSet classes |
|
416
|
|
|
|
|
|
|
if ( ! $class->isa('SOAP::WSDL::XSD::Typelib::AttributeSet')) { |
|
417
|
|
|
|
|
|
|
*{ "$class\::serialize" } = \&__serialize_complex; |
|
418
|
|
|
|
|
|
|
}; |
|
419
|
|
|
|
|
|
|
} |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub _set_element_form_qualified { |
|
422
|
|
|
|
|
|
|
$ELEMENT_FORM_QUALIFIED_OF{ $_[0] } = $_[1]; |
|
423
|
|
|
|
|
|
|
} |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# Just as fallback: return no attribute set class as default. |
|
426
|
|
|
|
|
|
|
# Subclasses may override |
|
427
|
|
|
|
|
|
|
sub __get_attr_class {}; |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
# hidden complex serializer |
|
430
|
|
|
|
|
|
|
sub __serialize_complex { |
|
431
|
|
|
|
|
|
|
# we work on @_ for performance. |
|
432
|
|
|
|
|
|
|
$_[1] ||= {}; # $option_ref |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
push @{ $_[1]->{ xmlns_stack } }, $_[0]->get_xmlns(); |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
# get content first (pass by reference to avoid copying) |
|
437
|
|
|
|
|
|
|
my $content_ref = $_[0]->_serialize($_[1]); # option_ref |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
pop @{ $_[1]->{ xmlns_stack } }; |
|
440
|
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
# do we have a empty element ? |
|
442
|
|
|
|
|
|
|
return $_[0]->start_tag({ %{ $_[1] }, empty => 1 }) |
|
443
|
|
|
|
|
|
|
if not length ${ $content_ref }; |
|
444
|
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
return join q{}, $_[0]->start_tag($_[1]), ${ $content_ref }, $_[0]->end_tag(); |
|
446
|
|
|
|
|
|
|
} |
|
447
|
|
|
|
|
|
|
|
|
448
|
|
|
|
|
|
|
sub get_xmlns { |
|
449
|
|
|
|
|
|
|
return q{} |
|
450
|
|
|
|
|
|
|
} |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
1; |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
__END__ |