import SOAP-WSDL 2.00_24 from CPAN

git-cpan-module:   SOAP-WSDL
git-cpan-version:  2.00_24
git-cpan-authorid: MKUTTER
git-cpan-file:     authors/id/M/MK/MKUTTER/SOAP-WSDL-2.00_24.tar.gz
This commit is contained in:
Martin Kutter
2007-11-17 14:07:49 -08:00
committed by Michael G. Schwern
parent b955c5ad79
commit 84b53d9261
169 changed files with 3995 additions and 3676 deletions

View File

@@ -48,20 +48,21 @@ my %LOOKUP = (
keep_alive => \%keep_alive_of,
);
sub readable { warn <<EOT;
'readable' has no effect any more. If you want formatted XML,
copy the debug output to your favorite XML editor and run the
source format command.
sub readable { carp <<'EOT';
'readable' has no effect any more. If you want formatted XML,
copy the debug output to your favorite XML editor and run the
source format command.
EOT
return;
}
sub set_readable; *set_readable = \&readable;
for my $method (keys %LOOKUP ) {
no strict qw(refs);
no strict qw(refs); ## no critic (ProhibitNoStrict)
*{ $method } = sub {
my $self = shift;
my $ident = ident $self;
my $ident = ident $self;
if (@_) {
$LOOKUP{ $method }->{ $ident } = shift;
return $self;
@@ -73,39 +74,36 @@ for my $method (keys %LOOKUP ) {
{ # just a BLOCK for scoping warnings.
# we need to roll our own for supporting
# SOAP::WSDL->new( key => value ) syntax,
# SOAP::WSDL->new( key => value ) syntax,
# like SOAP::Lite does. Class::Std enforces a single hash ref as
# parameters to new()
no warnings qw(redefine);
no warnings qw(redefine); ## no critic ProhibitNoWarnings;
sub new {
my $class = shift;
my %args_from = @_;
my ($class, %args_from) = @_;
my $self = \do { my $foo = undef };
bless $self, $class;
for (keys %args_from) {
my $method = $self->can("set_$_")
or croak "unknown parameter $_ passed to new";
$method->($self, $args_from{$_});
}
my $ident = ident $self;
my $ident = ident $self;
$self->wsdlinit() if ($wsdl_of{ $ident });
$client_of{ $ident } = SOAP::WSDL::Client->new();
return $self;
}
}
sub wsdlinit {
my $self = shift;
my ($self, %opt) = @_;
my $ident = ident $self;
my %opt = @_;
my $lwp = LWP::UserAgent->new(
$keep_alive_of{ $ident }
$keep_alive_of{ $ident }
? (keep_alive => 1)
: ()
: ()
);
my $response = $lwp->get( $wsdl_of{ $ident } );
croak $response->message() if ($response->code != 200);
@@ -117,10 +115,10 @@ sub wsdlinit {
# sanity checks
my $types = $wsdl_definitions->first_types()
or die "unable to extract schema from WSDL";
or croak "unable to extract schema from WSDL";
my $ns = $wsdl_definitions->get_xmlns()
or die "unable to extract XML Namespaces" . $wsdl_definitions->to_string;
( %{ $ns } ) or die "unable to extract XML Namespaces";
or croak "unable to extract XML Namespaces" . $wsdl_definitions->to_string;
( %{ $ns } ) or croak "unable to extract XML Namespaces";
# setup lookup variables
$definitions_of{ $ident } = $wsdl_definitions;
@@ -138,7 +136,7 @@ sub wsdlinit {
sub _wsdl_get_service :PRIVATE {
my $ident = ident shift;
my $wsdl = $definitions_of{ $ident };
return $service_of{ $ident } = $servicename_of{ $ident }
return $service_of{ $ident } = $servicename_of{ $ident }
? $wsdl->find_service( $wsdl->get_targetNamespace() , $servicename_of{ $ident } )
: $service_of{ $ident } = $wsdl->get_service()->[ 0 ];
} ## end sub _wsdl_get_service
@@ -150,28 +148,25 @@ sub _wsdl_get_port :PRIVATE {
return $port_of{ $ident } = $portname_of{ $ident }
? $service_of{ $ident }->get_port( $ns, $portname_of{ $ident } )
: $port_of{ $ident } = $service_of{ $ident }->get_port()->[ 0 ];
}
}
sub _wsdl_get_binding :PRIVATE {
my $self = shift;
my $ident = ident $self;
my $wsdl = $definitions_of{ $ident };
my $port = $port_of{ $ident } || $self->_wsdl_get_port();
$binding_of{ $ident } = $wsdl->find_binding( $port->expand( $port->get_binding() ) )
or die "no binding found for ", $port->get_binding();
or croak "no binding found for ", $port->get_binding();
return $binding_of{ $ident };
}
}
sub _wsdl_get_portType :PRIVATE {
my $self = shift;
my $ident = ident $self;
my $wsdl = $definitions_of{ $ident };
my $binding = $binding_of{ $ident } || $self->_wsdl_get_binding();
$porttype_of{ $ident } = $wsdl->find_portType( $binding->expand( $binding->get_type() ) )
or die "cannot find portType for " . $binding->get_type();
or croak "cannot find portType for " . $binding->get_type();
return $porttype_of{ $ident };
}
}
sub _wsdl_init_methods :PRIVATE {
my $self = shift;
my $ident = ident $self;
@@ -181,7 +176,7 @@ sub _wsdl_init_methods :PRIVATE {
# get bindings, portType, message, part(s) - use private methods for clear separation...
$self->_wsdl_get_service if not ($service_of{ $ident });
my $binding = $binding_of{ $ident } || $self->_wsdl_get_binding()
|| die "Can't find binding";
|| croak "Can't find binding";
my $portType = $porttype_of{ $ident } || $self->_wsdl_get_portType();
$method_info_of{ $ident } = {};
@@ -202,35 +197,34 @@ sub _wsdl_init_methods :PRIVATE {
$binding_operation->get_name() );
# 2. get input message name
my ( $prefix, $localname ) = split /:/,
my ( $prefix, $localname ) = split /:/xm,
$operation->first_input()->get_message();
# 3. get input message
my $message = $wsdl->find_message( $ns, $localname )
or die "Message {$ns}$localname not found in WSDL definition";
or croak "Message {$ns}$localname not found in WSDL definition";
if (my $body=$binding_operation->first_input()->first_body()) {
if ($body->get_parts()) {
$method->{ parts } = []; # make sure it's empty
my $message_part_ref = $message->get_part();
for my $name (split m{\s} , $body->get_parts() ) {
$name =~s{ \A [^:]+: }{}x; # throw away ns prefix
for my $name ( split m{\s}xm , $body->get_parts() ) {
$name =~s{ \A [^:]+: }{}xm; # throw away ns prefix
# could probably made more efficient, but our lists are
# usually quite short
push @{ $method->{ parts } },
push @{ $method->{ parts } },
grep { $_->get_name() eq $name } @{ $message_part_ref };
}
}
}
}
$method->{ parts } ||= $message->get_part();
# rpc / encoded methods may have a namespace specified.
# look it up and set it...
$method->{ namespace } = $binding_operation
? do {
my $input = $binding_operation->first_input();
$input ? $input->first_body()->get_namespace() : undef;
$method->{ namespace } = $binding_operation
? do {
my $input = $binding_operation->first_input();
$input ? $input->first_body()->get_namespace() : undef;
}
: undef;
@@ -244,9 +238,9 @@ sub call {
my ($self, $method, @data_from) = @_;
my $ident = ident $self;
my ($data, $header) = ref $data_from[0]
? ($data_from[0], $data_from[1] )
: (@data_from>1)
my ($data, $header) = ref $data_from[0]
? ($data_from[0], $data_from[1] )
: (@data_from>1)
? ( { @data_from }, undef )
: ( $data_from[0], undef );
@@ -254,22 +248,22 @@ sub call {
$self->_wsdl_init_methods() if not ($method_info_of{ $ident });
my $client = $client_of{ $ident };
# pass-through keep_alive if we need it...
$client->set_proxy( $proxy_of{ $ident }
$client->set_proxy( $proxy_of{ $ident }
|| $port_of{ $ident }->first_address()->get_location(),
$keep_alive_of{ $ident } ? (keep_alive => 1) : (),
$keep_alive_of{ $ident } ? (keep_alive => 1) : (),
);
$client->set_no_dispatch( $no_dispatch_of{ $ident } );
$client->set_outputxml( $outputxml_of{ $ident } ? 1 : 0 );
# only load ::Deserializer::SOM if we really need to deserialize to SOM.
# maybe we should introduce something like $output{ $ident } with a fixed
# maybe we should introduce something like $output{ $ident } with a fixed
# set of values - m{^(TREE|HASH|XML|SOM)$}xms ?
if ( ( ! $outputtree_of{ $ident } )
&& ( ! $outputhash_of{ $ident } )
&& ( ! $outputxml_of{ $ident } )
&& ( ! $outputhash_of{ $ident } )
&& ( ! $outputxml_of{ $ident } )
&& ( ! $no_dispatch_of{ $ident } ) ) {
require SOAP::WSDL::Deserializer::SOM;
$client->set_deserializer( SOAP::WSDL::Deserializer::SOM->new() );
@@ -278,18 +272,19 @@ sub call {
my $method_info = $method_info_of{ $ident }->{ $method };
# TODO serialize both header and body, not only header
my (@response) = (blessed $data)
my (@response) = (blessed $data)
? $client->call( {
operation => $method,
soap_action => $method_info->{ soap_action },
}, $data )
: do {
my $content = '';
my $content = q{};
# TODO support RPC-encoding: Top-Level element + namespace...
foreach my $part ( @{ $method_info->{ parts } } ) {
$content .= $part->serialize( $method, $data,
$content .= $part->serialize( $method, $data,
{
%{ $serialize_options_of{ $ident } },
%{ $serialize_options_of{ $ident } }
} );
}
$client->call(
@@ -297,21 +292,20 @@ sub call {
operation => $method,
soap_action => $method_info->{ soap_action }
},
# absolutely stupid, but we need a reference which
# absolutely stupid, but we need a reference which
# serializes to XML on stringification...
SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType->new({
value => $content
}),
}),
SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType->new({
value => $header
})
);
};
return unless @response; # nothing to do for one-ways
return if not @response; # nothing to do for one-ways
return wantarray ? @response : $response[0];
}
}
1;
__END__
@@ -327,7 +321,7 @@ SOAP::WSDL - SOAP with WSDL support
For creating Perl classes instrumenting a web service with a WSDL definition,
read L<SOAP::WSDL::Manual>.
For using an interpreting (thus slow and somewhat troublesome) WSDL based
For using an interpreting (thus slow and somewhat troublesome) WSDL based
SOAP client, which mimics L<SOAP::Lite|SOAP::Lite>'s API, read on.
=head1 SYNOPSIS
@@ -337,12 +331,12 @@ SOAP client, which mimics L<SOAP::Lite|SOAP::Lite>'s API, read on.
);
my $result = $soap->call('MyMethod', %data);
=head1 DESCRIPTION
SOAP::WSDL provides easy access to Web Services with WSDL descriptions.
The WSDL is parsed and stored in memory.
The WSDL is parsed and stored in memory.
Your data is serialized according to the rules in the WSDL.
@@ -357,7 +351,7 @@ Constructor. All parameters passed are passed to the corresponding methods.
=head2 call
Performs a SOAP call. The result is either an object tree (with outputtree),
a hash reference (with outputhash), plain XML (with outputxml) or a SOAP::SOM
a hash reference (with outputhash), plain XML (with outputxml) or a SOAP::SOM
object (with neither of the above set).
call() can be called in different ways:
@@ -374,13 +368,13 @@ Does not support SOAP header data.
my $result = $soap->call('method', $body_ref, $header_ref );
Does support SOAP header data. $body_ref and $header ref may either be
Does support SOAP header data. $body_ref and $header ref may either be
hash refs or SOAP::WSDL::XSD::Typelib::* derived objects.
Result headers are accessible via the result SOAP::SOM object.
If outputtree or outputhash are set, you may also use the following to
access response header data:
If outputtree or outputhash are set, you may also use the following to
access response header data:
my ($body, $header) = $soap->call('method', $body_ref, $header_ref );
@@ -396,33 +390,33 @@ Is called automatically from call() if not called directly before.
portname
call
You may set servicename and portname by passing them as attributes to
You may set servicename and portname by passing them as attributes to
wsdlinit:
$soap->wsdlinit(
servicename => 'MyService',
portname => 'MyPort'
portname => 'MyPort',
);
=head1 CONFIGURATION METHODS
=head2 outputtree
When outputtree is set, SOAP::WSDL will return an object tree instead of a
When outputtree is set, SOAP::WSDL will return an object tree instead of a
SOAP::SOM object.
You have to specify a class_resolver for this to work. See
You have to specify a class_resolver for this to work. See
L<class_resolver|class_resolver>
=head2 class_resolver
Set the class resolver class (or object).
Class resolvers must implement the method get_class which has to return the
name of the class name for deserializing a XML node at the current XPath
Class resolvers must implement the method get_class which has to return the
name of the class name for deserializing a XML node at the current XPath
location.
Class resolvers are typically generated by using the generate_typemap method
Class resolvers are typically generated by using the generate_typemap method
of a SOAP::WSDL::Generator subclass.
Example:
@@ -442,18 +436,18 @@ Class resolver
'Person/Name' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Person/FirstName' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
);
sub get_class { return $typemap{ $_[1] } };
1;
You'll need a MyPersonClass module in your search path for this to work - see
SOAP::WSDL::XSD::ComplexType on how to build / generate one.
You'll need a MyPersonClass module in your search path for this to work - see
SOAP::WSDL::XSD::ComplexType on how to build / generate one.
=head2 servicename
$soap->servicename('Name');
Sets the service to operate on. If no service is set via servicename, the
Sets the service to operate on. If no service is set via servicename, the
first service found is used.
Returns the soap object, so you can chain calls like
@@ -464,7 +458,7 @@ Returns the soap object, so you can chain calls like
$soap->portname('Name');
Sets the port to operate on. If no port is set via portname, the
Sets the port to operate on. If no port is set via portname, the
first port found is used.
Returns the soap object, so you can chain calls like
@@ -473,14 +467,14 @@ Returns the soap object, so you can chain calls like
=head2 no_dispatch
When set, call() returns the plain request XML instead of dispatching the
When set, call() returns the plain request XML instead of dispatching the
SOAP call to the SOAP service. Handy for testing/debugging.
=head1 ACCESS TO SOAP::WSDL's internals
=head2 get_client / set_client
Returns the SOAP client implementation used (normally a SOAP::WSDL::Client
Returns the SOAP client implementation used (normally a SOAP::WSDL::Client
object).
=head1 EXAMPLES
@@ -489,24 +483,24 @@ See the examples/ directory.
=head1 Differences to previous versions
=over
=over
=item * WSDL handling
SOAP::WSDL 2 is a complete rewrite. While SOAP::WSDL 1.x attempted to
process the WSDL file on the fly by using XPath queries, SOAP:WSDL 2 uses a
Expat handler for parsing the WSDL and building up a object tree representing
SOAP::WSDL 2 is a complete rewrite. While SOAP::WSDL 1.x attempted to
process the WSDL file on the fly by using XPath queries, SOAP:WSDL 2 uses a
Expat handler for parsing the WSDL and building up a object tree representing
it's content.
The object tree has two main functions: It knows how to serialize data passed
The object tree has two main functions: It knows how to serialize data passed
as hash ref, and how to render the WSDL elements found into perl classes.
Yup your're right, there's a builting code generation facility. Read
Yup your're right, there's a builting code generation facility. Read
L<SOAP::WSDL::Manual> for using it.
=item * no_dispatch
=item * no_dispatch
call() with no_dispatch set to true now returns the complete SOAP request
call() with no_dispatch set to true now returns the complete SOAP request
envelope, not only the body's content.
=item * outputxml
@@ -526,21 +520,21 @@ You may pass the servicename and portname as attributes to wsdlinit, though.
=head2 readable
readable is a no-op in SOAP::WSDL. Actually, the XML output from SOAP::Lite
readable is a no-op in SOAP::WSDL. Actually, the XML output from SOAP::Lite
is hardly readable, either with readable switched on.
If you need readable XML messages, I suggest using your favorite XML editor
If you need readable XML messages, I suggest using your favorite XML editor
for displaying and formatting.
=head2 Message style/encoding
While SOAP::Lite supports rpc/encoded style/encoding only, SOAP::WSDL currently
While SOAP::Lite supports rpc/encoded style/encoding only, SOAP::WSDL currently
supports document/literal style/encoding.
=head2 autotype / type information
SOAP::Lite defaults to transmitting XML type information by default, where
SOAP::WSDL defaults to leaving it out.
SOAP::Lite defaults to transmitting XML type information by default, where
SOAP::WSDL defaults to leaving it out.
autotype(1) might even be broken in SOAP::WSDL - it's not well-tested, yet.
@@ -556,13 +550,13 @@ This is the default. SOAP::Lite is required for outputting SOAP::SOM objects.
=item * Object trees.
This is the recommended output format.
You need a class resolver (typemap) for outputting object trees.
This is the recommended output format.
You need a class resolver (typemap) for outputting object trees.
See L<class_resolver|class_resolver> above.
=item * Hash refs
This is for convnience: A single hash ref containing the content of the
This is for convnience: A single hash ref containing the content of the
SOAP body.
=item * xml
@@ -588,26 +582,26 @@ SOAP::WSDL::Client and implementing something like
$soap_wsdl_client->call( mySoapMethod, @_);
}
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
such interfaces.
=head2 Debugging / Tracing
While SOAP::Lite features a global tracing facility, SOAP::WSDL
While SOAP::Lite features a global tracing facility, SOAP::WSDL
allows to switch tracing on/of on a per-object base.
This has to be done in the SOAP client used by SOAP::WSDL - see
L<get_client|get_client> for an example and L<SOAP::WSDL::Client> for
This has to be done in the SOAP client used by SOAP::WSDL - see
L<get_client|get_client> for an example and L<SOAP::WSDL::Client> for
details.
=head1 Bugs and Limitations
=head1 BUGS AND LIMITATIONS
=over
=over
=item * perl 5.8.0 or higher required
SOAP::WSDL needs perl 5.8.0 or higher. This is due to a bug in perls
before - see http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/929746 for details.
SOAP::WSDL needs perl 5.8.0 or higher. This is due to a bug in perls
before - see http://aspn.activestate.com/ASPN/Mail/Message/perl5-porters/929746 for details.
=item * Apache SOAP datatypes are not supported
@@ -627,7 +621,7 @@ The following XML Schema definitions varieties are not supported:
union
simpleContent
The following XML Schema definition content model is only partially
The following XML Schema definition content model is only partially
supported:
complexContent - only restriction variety supported
@@ -636,10 +630,10 @@ See L<SOAP::WSDL::Manual::XSD> for details.
=item * Serialization of hash refs dos not work for ambiguos values
If you have list elements with multiple occurences allowed, SOAP::WSDL
If you have list elements with multiple occurences allowed, SOAP::WSDL
has no means of finding out which variant you meant.
Passing in item => [1,2,3] could serialize to
Passing in item => [1,2,3] could serialize to
<item>1 2</item><item>3</item>
<item>1</item><item>2 3</item>
@@ -648,7 +642,7 @@ Ambiguos data can be avoided by providing data as objects.
=item * XML Schema facets
Almost no XML schema facets are implemented yet. The only facets
Almost no XML schema facets are implemented yet. The only facets
currently implemented are:
fixed
@@ -677,20 +671,20 @@ The following facets have no influence yet:
Full featured SOAP-library, little WSDL support. Supports rpc-encoded style only. Many protocols supported.
=item * <XML::Compile::WSDL|XML::Compile::WSDL>
=item * L<XML::Compile::WSDL|XML::Compile::WSDL> / L<XML::Compile::SOAP|XML::Compile::SOAP>
A promising-looking approach derived from a cool functional DOM-based XML schema parser.
Will support encoding/decoding of SOAP messages based on WSDL definitions.
Not yet finished at the time of writing - but you may wish to give it a try, especially
if you need to adhere very closely to the XML Schema / WSDL specs.
Not yet finished at the time of writing - but you may wish to give it a try, especially
if you need to adhere very closely to the XML Schema / WSDL specs.
=back
=head2 Sources of documentation
=over
=over
=item * SOAP::WSDL homepage at sourceforge.net
@@ -704,30 +698,30 @@ L<http://www.cpanforum.com/dist/SOAP-WSDL>
=head1 ACKNOWLEDGMENTS
There are many people out there who fostered SOAP::WSDL's developement.
There are many people out there who fostered SOAP::WSDL's developement.
I would like to thank them all (and apologize to all those I have forgotten).
Giovanni S. Fois wrote a improved version of SOAP::WSDL (which eventually
Giovanni S. Fois wrote a improved version of SOAP::WSDL (which eventually
became v1.23)
David Bussenschutt, Damian A. Martinez Gelabert, Dennis S. Hennen, Dan Horne,
Peter Orvos, Mark Overmeer, Jon Robens, Isidro Vila Verde and Glenn Wood
Peter Orvos, Mark Overmeer, Jon Robens, Isidro Vila Verde and Glenn Wood
spotted bugs and/or suggested improvements in the 1.2x releases.
Andreas 'ac0v' Specht constantly asked for better performance.
JT Justman provided some early feedback for the 2.xx pre-releases.
JT Justman provided early feedback for the 2.xx pre-releases.
Numerous people sent me their real-world WSDL files for testing. Thank you.
Paul Kulchenko and Byrne Reese wrote and maintained SOAP::Lite and
Paul Kulchenko and Byrne Reese wrote and maintained SOAP::Lite and
thus provided a base (and counterpart) for SOAP::WSDL.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
@@ -736,10 +730,10 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 332 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: WSDL.pm 332 2007-10-19 07:29:03Z kutterma $
$Id: WSDL.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL.pm $
=cut

View File

@@ -3,7 +3,7 @@ use strict;
use warnings;
use Class::Std::Storable;
use List::Util qw(first);
use Carp qw(confess);
use Carp qw(croak carp confess);
our $VERSION='2.00_17';
@@ -18,6 +18,7 @@ sub DEMOLISH {
my $self = shift;
# delete upward references
delete $parent_of{ ident $self };
return;
}
sub STORABLE_freeze_pre :CUMULATIVE {};
@@ -31,8 +32,8 @@ sub _accept {
$class =~ s{ \A SOAP::WSDL:: }{}xms;
$class =~ s{ (:? :: ) }{_}gxms;
my $method = "visit_$class";
no strict qw(refs);
shift->$method( $self );
no strict qw(refs); ## no critic ProhibitNoStrict
return shift->$method( $self );
}
# unfortunately, AUTOMETHOD is SLOW.
@@ -46,13 +47,13 @@ sub AUTOMETHOD {
if ($subname =~s{^push_}{}xms) {
my $getter = "get_$subname";
my $setter = "set_$subname";
## Checking here is paranoid - will fail fatally if
## Checking here is paranoid - will fail fatally if
## there is no setter...
## And we would have to check getters, too.
## Maybe do it the Conway way via the Symbol table...
## ... can is way slow...
return sub {
no strict qw(refs);
no strict qw(refs); ## no critic ProhibitNoStrict
my $old_value = $self->$getter();
# Listify if not a list ref
$old_value = $old_value ? [ $old_value ] : [] if not ref $old_value;
@@ -85,13 +86,12 @@ sub AUTOMETHOD {
}
sub init {
my $self = shift;
my @args = @_;
my ($self, @args) = @_;
foreach my $value (@args)
{
die @args if (not defined ($value->{ Name }));
croak @args if (not defined ($value->{ Name }));
if ($value->{ Name } =~m{^xmlns\:}xms) {
die $xmlns_of{ ident $self }
croak $xmlns_of{ ident $self }
if ref $xmlns_of{ ident $self } ne 'HASH';
# add namespaces
@@ -115,16 +115,27 @@ sub init {
sub expand {
my ($self, , $qname) = @_;
my ($prefix, $localname) = split /:/, $qname;
my ($prefix, $localname) = split /:/x, $qname;
my %ns_map = reverse %{ $self->get_xmlns() };
return ($ns_map{ $prefix }, $localname) if ($ns_map{ $prefix });
if (my $parent = $self->get_parent()) {
return $parent->expand($qname);
}
confess "unbound prefix $prefix found for $prefix:$localname";
}
sub _expand;
sub _expand;
*_expand = \&expand;
1;
__END__
# REPOSITORY INFORMATION
#
# $Rev: 332 $
# $LastChangedBy: kutterma $
# $Id: WSDL.pm 332 2007-10-19 07:29:03Z kutterma $
# $HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL.pm $
#

View File

@@ -33,15 +33,15 @@ sub BUILD {
$self->set_proxy( $attrs_of_ref->{ proxy } );
delete $attrs_of_ref->{ proxy };
}
return;
}
sub get_proxy {
sub get_proxy { ## no critic RequireArgUnpacking
return $_[0]->get_transport();
}
sub set_proxy {
my ($self, @args_from) = @_;
my ($self, @args_from) = @_;
my $ident = ident $self;
# remember old value to return it later - Class::Std does so, too
@@ -49,7 +49,7 @@ sub set_proxy {
# accept both list and list ref args
@args_from = @{ $args_from[0] } if ref $args_from[0];
# remember endpoint
$endpoint_of{ $ident } = $args_from[0];
@@ -66,22 +66,22 @@ sub set_soap_version {
# remember old value to return it later - Class::Std does so, too
my $soap_version = $soap_version_of{ $ident };
# re-setting the soap version invalidates the
# re-setting the soap version invalidates the
# serializer object
delete $serializer_of{ $ident };
delete $deserializer_of{ $ident };
$soap_version_of{ $ident } = shift;
$soap_version_of{ $ident } = shift;
return $soap_version;
}
# Mimic SOAP::Lite's behaviour for getter/setter routines
SUBFACTORY: {
no strict qw(refs);
for (qw(class_resolver no_dispatch outputxml proxy)) {
my $setter = "set_$_";
my $getter = "get_$_";
no strict qw(refs); ## no critic ProhibitNoStrict
*{ $_ } = sub { my $self = shift;
if (@_) {
$self->$setter(@_);
@@ -96,33 +96,32 @@ sub call {
my ($self, $method, @data_from) = @_;
my $ident = ident $self;
# the only valid idiom for calling a method with both a header and a body
# the only valid idiom for calling a method with both a header and a body
# is
# ->call($method, $body_ref, $header_ref);
#
# These other idioms all assume an empty header:
# ->call($method, %body_of); # %body_of is a hash
# ->call($method, $body); # $body is a scalar
my ($data, $header) = ref $data_from[0]
? ($data_from[0], $data_from[1] )
: (@data_from>1)
my ($data, $header) = ref $data_from[0]
? ($data_from[0], $data_from[1] )
: (@data_from>1)
? ( { @data_from }, undef )
: ( $data_from[0], undef );
# get operation name and soap_action
my ($operation, $soap_action) = (ref $method eq 'HASH')
my ($operation, $soap_action) = (ref $method eq 'HASH')
? ( $method->{ operation }, $method->{ soap_action } )
: (blessed $data
: (blessed $data
&& $data->isa('SOAP::WSDL::XSD::Typelib::Builtin::anyType'))
? ( $method , (join '/', $data->get_xmlns(), $method) )
? ( $method , (join q{/}, $data->get_xmlns(), $method) )
: ( $method, q{} );
$serializer_of{ $ident } ||= SOAP::WSDL::Factory::Serializer->get_serializer({
soap_version => $self->get_soap_version(),
});
my $envelope = $serializer_of{ $ident }->serialize({
method => $operation,
method => $operation,
body => $data,
header => $header,
});
@@ -131,7 +130,7 @@ sub call {
# always quote SOAPAction header.
# WS-I BP 1.0 R1109
if ($soap_action) {
if ($soap_action) {
$soap_action =~s{\A(:?"|')?}{"}xms;
$soap_action =~s{(:?"|')?\Z}{"}xms;
}
@@ -140,9 +139,9 @@ sub call {
}
# get response via transport layer.
# Normally, SOAP::Lite's transport layer is used, though users
# Normally, SOAP::Lite's transport layer is used, though users
# may provide their own.
my $transport = $self->get_transport();
my $transport = $self->get_transport();
my $response = $transport->send_receive(
endpoint => $self->get_endpoint(),
content_type => $content_type_of{ $ident },
@@ -165,14 +164,14 @@ sub call {
# Try deserializing response - there may be some,
# even if transport did not succeed (got a 500 response)
if ( $response ) {
my ($result_body, $result_header) = eval {
$deserializer_of{ $ident }->deserialize( $response );
my ($result_body, $result_header) = eval {
$deserializer_of{ $ident }->deserialize( $response );
};
if (not $@) {
return wantarray
return wantarray
? ($result_body, $result_header)
: $result_body;
}
}
return $deserializer_of{ $ident }->generate_fault({
code => 'soap:Server',
role => 'urn:localhost',
@@ -206,12 +205,20 @@ __END__
SOAP::WSDL::Client - SOAP::WSDL's SOAP Client
=head1 SYNOPSIS
use SOAP::WSDL::Client;
my $soap = SOAP::WSDL::Client->new({
proxy => 'http://www.example.org/webservice/test'
});
$soap->call( \%method, $body, $header);
=head1 METHODS
=head2 call
$soap->call( \%method, \@parts );
%method is a hash with the following keys:
Name Description
@@ -219,7 +226,7 @@ SOAP::WSDL::Client - SOAP::WSDL's SOAP Client
operation operation name
soap_action SOAPAction HTTP header to use
style Operation style. One of (document|rpc)
use SOAP body encoding. One of (literal|encoded)
use SOAP body encoding. One of (literal|encoded)
The style and use keys have no influence yet.
@@ -229,12 +236,11 @@ For backward compatibility, call may also be called as below:
$soap->call( $method, \@parts );
In this case, $method is the SOAP operation name, and the SOAPAction header
is guessed from the first part's namespace and the operation name (which is
mostly correct, but may fail). Operation style and body encoding are assumed to
In this case, $method is the SOAP operation name, and the SOAPAction header
is guessed from the first part's namespace and the operation name (which is
mostly correct, but may fail). Operation style and body encoding are assumed to
be document/literal
=head2 Configuration methods
=head3 outputxml
@@ -243,17 +249,17 @@ be document/literal
When set, call() returns the raw XML of the SOAP Envelope.
=head3 set_content_type
=head3 set_content_type
$soap->set_content_type('application/xml; charset: utf8');
Sets the content type and character encoding.
Sets the content type and character encoding.
You probably should not use a character encoding different from utf8:
SOAP::WSDL::Client will not convert the request into a different encoding
You probably should not use a character encoding different from utf8:
SOAP::WSDL::Client will not convert the request into a different encoding
(yet).
To leave out the encoding, just set the content type without appendet charset
To leave out the encoding, just set the content type without appendet charset
like in
text/xml
@@ -269,8 +275,8 @@ Default:
When set to a true value, tracing (via warn) is enabled.
When set to a code reference, this function will be called on every
trace call, making it really easy for you to set up log4perl logging
When set to a code reference, this function will be called on every
trace call, making it really easy for you to set up log4perl logging
or whatever you need.
=head2 Features different from SOAP::Lite
@@ -336,28 +342,28 @@ SOAP::WSDL::Client and implementing something like
$soap_wsdl_client->call( mySoapMethod, @_);
}
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
You may even do this in a class factory - see L<wsdl2perl.pl> for creating
such interfaces.
=head1 Troubleshooting
=head1 TROUBLESHOOTING
=head2 Accessing protected web services
Accessing protected web services is very specific for the transport
Accessing protected web services is very specific for the transport
backend used.
In general, you may pass additional arguments to the set_proxy method (or
a list ref of the web service address and any additional arguments to the
In general, you may pass additional arguments to the set_proxy method (or
a list ref of the web service address and any additional arguments to the
new method's I<proxy> argument).
Refer to the appropriate transport module for documentation.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under the same
terms as perl itself
=head1 AUTHOR
@@ -365,10 +371,10 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 303 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Client.pm 303 2007-10-01 18:51:50Z kutterma $
$Id: Client.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
=cut

View File

@@ -4,76 +4,57 @@ use warnings;
use base 'SOAP::WSDL::Client';
use Scalar::Util qw(blessed);
our $VERSION = '2.00_17';
our $VERSION = '2.00_24';
sub call {
my ($self, $method, $body, $header) = @_;
if (not blessed $body) {
$body = {} if not defined $body;
$body = {} if not defined $body;
my $class = $method->{ body }->{ parts }->[0];
eval "require $class" || die $@;
$body = $class->new($body);
$body = $class->new($body);
}
# if we have a header
if (%{ $method->{ header } }) {
if (not blessed $header) {
my $class = $method->{ header }->{ parts }->[0];
eval "require $class" || die $@;
$header = $class->new($header);
$header = $class->new($header);
}
}
return $self->SUPER::call($method, $body, $header);
return $self->SUPER::call($method, $body, $header);
}
#sub __create_new {
# my ($package, %args_of) = @_;
#
# no strict qw(refs);
# no warnings qw(redefine);
#
# # TODO factor out and replace by generated START method
# *{ "$package\::new" } = sub {
# my $class = shift;
# my $self = $class->SUPER::new({
# proxy => $args_of{ proxy },
# class_resolver => $args_of{ class_resolver }
# });
# bless $self, $class;
# return $self;
# }
#}
sub __create_methods {
my ($package, %info_of) = @_;
no strict qw(refs);
no warnings qw(redefine);
for my $method (keys %info_of){
my ($soap_action, @parts);
# up to 2.00_10 we had list refs...
if (ref $info_of{ $method }eq 'HASH') {
@parts = @{ $info_of{ $method }->{ parts } };
$soap_action = $info_of{ $method }->{ soap_action };
}
else {
@parts = @{ $info_of{ $method } };
$soap_action = ();
}
*{ "$package\::$method" } = sub {
my $self = shift;
my @param = map {
my ($package, %info_of) = @_;
no strict qw(refs);
no warnings qw(redefine);
for my $method (keys %info_of){
my ($soap_action, @parts);
# up to 2.00_10 we had list refs...
if (ref $info_of{ $method }eq 'HASH') {
@parts = @{ $info_of{ $method }->{ parts } };
$soap_action = $info_of{ $method }->{ soap_action };
}
else {
die "Pre-v2.00_10 Interfaces are no longer supported. Please re-generate your interface.";
}
*{ "$package\::$method" } = sub {
my $self = shift;
my @param = map {
my $data = shift || {};
eval "require $_";
$_->new( $data );
} @parts;
return $self->SUPER::call( {
operation => $method,
soap_action => $soap_action,
}, @param );
} @parts;
return $self->SUPER::call( {
operation => $method,
soap_action => $soap_action,
}, @param );
}
}
}
@@ -92,24 +73,20 @@ SOAP::WSDL::Client::Base - Factory class for WSDL-based SOAP access
package MySoapInterface;
use SOAP::WSDL::Client::Base;
__PACKAGE__->__create_new(
proxy => 'http://somewhere.over.the.rainbow',
class_resolver => 'Typemap::MySoapInterface'
);
__PACKAGE__->__create_methods( qw(one two three) );
1;
=head1 DESCRIPTION
Factory class for creating interface classes. Should probably be renamed to
Factory class for creating interface classes. Should probably be renamed to
SOAP::WSDL::Factory::Interface...
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under the same
terms as perl itself
=head1 AUTHOR
@@ -117,9 +94,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 323 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Base.pm 323 2007-10-17 15:23:05Z kutterma $
$Id: Base.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client/Base.pm $
=cut

View File

@@ -19,7 +19,7 @@ my %service_of :ATTR(:name<service> :default<()>);
my %namespace_of :ATTR(:name<namespace> :default<()>);
# must be attr for Class::Std::Storable
my %attributes_of :ATTR();
my %attributes_of :ATTR();
%attributes_of = (
binding => \%binding_of,
message => \%message_of,
@@ -29,30 +29,21 @@ my %attributes_of :ATTR();
# Function factory - we could be writing this method for all %attribute
# keys, too, but that's just C&P (eehm, Copy & Paste...)
BLOCK: {
no strict qw/refs/;
BLOCK: {
foreach my $method(keys %attributes_of ) {
no strict qw/refs/; ## no critic ProhibitNoStrict
*{ "find_$method" } = sub {
my ($self, @args_from) = @_;
@args_from = @{ $args_from[0] } if ref $args_from[0] eq 'ARRAY';
return first {
$_->get_targetNamespace() eq $args_from[0]
&& $_->get_name() eq $args_from[1]
return first {
$_->get_targetNamespace() eq $args_from[0]
&& $_->get_name() eq $args_from[1]
}
@{ $attributes_of{ $method }->{ ident $self } };
};
}
}
#sub listify {
# my $data = shift;
# return if not defined $data;
# return [ $data ] if not ref $data;
# return [ $data ] if not ref $data eq 'ARRAY';
# return $data;
#}
1;
=pod
@@ -67,7 +58,7 @@ SOAP::WSDL::Definitions - model a WSDL E<gt>definitionsE<lt> element
=head2 first_service get_service set_service push_service
Accessors/Mutators for accessing / setting the E<gt>serviceE<lt> child
Accessors/Mutators for accessing / setting the E<gt>serviceE<lt> child
element(s).
=head2 find_service
@@ -78,7 +69,7 @@ Returns the service matching the namespace/localname pair passed as arguments.
=head2 first_binding get_binding set_binding push_binding
Accessors/Mutators for accessing / setting the E<gt>bindingE<lt> child
Accessors/Mutators for accessing / setting the E<gt>bindingE<lt> child
element(s).
=head2 find_service
@@ -89,7 +80,7 @@ Returns the binding matching the namespace/localname pair passed as arguments.
=head2 first_portType get_portType set_portType push_portType
Accessors/Mutators for accessing / setting the E<gt>portTypeE<lt> child
Accessors/Mutators for accessing / setting the E<gt>portTypeE<lt> child
element(s).
=head2 find_portType
@@ -100,7 +91,7 @@ Returns the portType matching the namespace/localname pair passed as arguments.
=head2 first_message get_message set_message push_message
Accessors/Mutators for accessing / setting the E<gt>messageE<lt> child
Accessors/Mutators for accessing / setting the E<gt>messageE<lt> child
element(s).
=head2 find_service
@@ -111,19 +102,26 @@ Returns the message matching the namespace/localname pair passed as arguments.
=head2 first_types get_types set_types push_types
Accessors/Mutators for accessing / setting the E<gt>typesE<lt> child
Accessors/Mutators for accessing / setting the E<gt>typesE<lt> child
element(s).
=head1 LICENSE
=head1 LICENSE and COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Definitions.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Definitions.pm $
=cut

View File

@@ -8,11 +8,11 @@ use SOAP::WSDL::Expat::Message2Hash;
use SOAP::WSDL::Factory::Deserializer;
SOAP::WSDL::Factory::Deserializer->register( '1.1', __PACKAGE__ );
our $VERSION='2.00_17';
our $VERSION='2.00_24';
sub BUILD {
my ($self, $ident, $args_of_ref) = @_;
# ignore all options
for (keys %{ $args_of_ref }) {
delete $args_of_ref->{ $_ }
@@ -21,7 +21,7 @@ sub BUILD {
sub deserialize {
my ($self, $content) = @_;
my $parser = SOAP::WSDL::Expat::Message2Hash->new();
eval { $parser->parse_string( $content ) };
if ($@) {
@@ -41,7 +41,7 @@ sub generate_fault {
faultcode => $args_from_ref->{ code } || 'soap:Client',
faultactor => $args_from_ref->{ role } || 'urn:localhost',
faultstring => $args_from_ref->{ message } || "Unknown error"
});
});
}
1;
@@ -61,11 +61,11 @@ Deserializer for creating perl hash refs as result of a SOAP call.
=head2 Output structure
The XML structure is converted into a perl data structure consisting of
The XML structure is converted into a perl data structure consisting of
hash and or list references. List references are used for holding array data.
SOAP::WSDL::Deserializer::Hash creates list references always at the maximum
depth possible.
SOAP::WSDL::Deserializer::Hash creates list references always at the maximum
depth possible.
Examples:
@@ -91,16 +91,16 @@ Examples:
Perl:
{
MyDataArray => {
MyData => [
{ int => 1 },
MyData => [
{ int => 1 },
{ int => 1 }
]
}
}
List reference creation is triggered by the second occurance of an element.
XML Array types with one element only will not be represented as list
references.
List reference creation is triggered by the second occurance of an element.
XML Array types with one element only will not be represented as list
references.
=head1 USAGE
@@ -108,15 +108,15 @@ All you need to do is to use SOAP::WSDL::Deserializer::Hash.
SOAP::WSDL::Deserializer::Hash autoregisters itself for SOAP1.1 messages
You may register SOAP::WSDLDeserializer::Hash for other SOAP Versions by
You may register SOAP::WSDLDeserializer::Hash for other SOAP Versions by
calling
SOAP::Factory::Deserializer->register('1.2',
SOAP::Factory::Deserializer->register('1.2',
SOAP::WSDL::Deserializer::Hash)
=head1 Limitations
=over
=over
=item * Namespaces
@@ -134,17 +134,17 @@ All XML attributes are ignored.
=item * generate_fault
SOAP::WSDL::Deserializer::Hash will die with a SOAP::WSDL::Fault11 object when
SOAP::WSDL::Deserializer::Hash will die with a SOAP::WSDL::Fault11 object when
a parse error appears
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
@@ -152,9 +152,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 176 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Serializer.pm 176 2007-08-31 15:28:29Z kutterma $
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
$Id: Hash.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Deserializer/Hash.pm $
=cut

View File

@@ -2,15 +2,15 @@ package SOAP::WSDL::Deserializer::SOM;
use strict;
use warnings;
our $VERSION = '2.00_15';
our $VERSION = '2.00_24';
our @ISA;
eval {
eval {
require SOAP::Lite;
push @ISA, 'SOAP::Deserializer';
push @ISA, 'SOAP::Deserializer';
}
or die "Cannot load SOAP::Lite.
Cannot deserialize to SOM object without SOAP::Lite.
or die "Cannot load SOAP::Lite.
Cannot deserialize to SOM object without SOAP::Lite.
Please install SOAP::Lite.";
sub generate_fault {
@@ -48,29 +48,27 @@ This package is here for two reasons:
=item * Compatibility
You don't have to change the rest of your SOAP::Lite based app when switching
to SOAP::WSDL, but can just use SOAP::WSDL::Deserializer::SOM to get back the
You don't have to change the rest of your SOAP::Lite based app when switching
to SOAP::WSDL, but can just use SOAP::WSDL::Deserializer::SOM to get back the
same objects as you were used to.
=item * Completeness
SOAP::Lite covers much more of the SOAP specification than SOAP::WSDL.
SOAP::Lite covers much more of the SOAP specification than SOAP::WSDL.
SOAP::WSDL::Deserializer::SOM can be used for content which cannot be
deserialized by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
This may be XML including mixed content, attachements and other XML data not
(yet) handled by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
SOAP::WSDL::Deserializer::SOM can be used for content which cannot be
deserialized by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
This may be XML including mixed content, attachements and other XML data not
(yet) handled by L<SOAP::WSDL::Deserializer::SOAP11|SOAP::WSDL::Deserializer::SOAP11>.
=back
SOAP::WSDL::Deserializer::SOM is a subclass of L<SOAP::Deserializer|SOAP::Deserializer>
from the L<SOAP::Lite|SOAP::Lite> package.
You may
SOAP::WSDL::Deserializer::SOM is a subclass of L<SOAP::Deserializer|SOAP::Deserializer>
from the L<SOAP::Lite|SOAP::Lite> package.
=head1 USAGE
SOAP::WSDL::Deserializer will not auroregister itself - to use it for a particular
SOAP::WSDL::Deserializer will not auroregister itself - to use it for a particular
SOAP version just use the following lines:
my $soap_version = '1.1'; # or '1.2', further versions may appear.
@@ -87,7 +85,7 @@ SOAP version just use the following lines:
=item * No on_fault handler
You cannot specify what to do when an error occurs - SOAP::WSDL will die
You cannot specify what to do when an error occurs - SOAP::WSDL will die
with a SOAP::Fault object on transport errors.
=back
@@ -98,17 +96,17 @@ with a SOAP::Fault object on transport errors.
=item * generate_fault
SOAP::WSDL::Deserializer::SOM will die with a SOAP::Fault object on calls
SOAP::WSDL::Deserializer::SOM will die with a SOAP::Fault object on calls
to generate_fault.
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
@@ -116,9 +114,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 176 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Serializer.pm 176 2007-08-31 15:28:29Z kutterma $
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
$Id: SOM.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Deserializer/SOM.pm $
=cut

View File

@@ -5,13 +5,13 @@ use Class::Std::Storable;
use SOAP::WSDL::SOAP::Typelib::Fault11;
use SOAP::WSDL::Expat::MessageParser;
our $VERSION='2.00_21';
our $VERSION='2.00_24';
my %class_resolver_of :ATTR(:name<class_resolver> :default<()>);
sub BUILD {
my ($self, $ident, $args_of_ref) = @_;
# ignore all options except 'class_resolver'
for (keys %{ $args_of_ref }) {
delete $args_of_ref->{ $_ } if $_ ne 'class_resolver';
@@ -21,7 +21,7 @@ sub BUILD {
sub deserialize {
my ($self, $content) = @_;
my $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => $class_resolver_of{ ident $self },
});
@@ -43,7 +43,64 @@ sub generate_fault {
faultcode => $args_from_ref->{ code } || 'soap:Client',
faultactor => $args_from_ref->{ role } || 'urn:localhost',
faultstring => $args_from_ref->{ message } || "Unknown error"
});
});
}
1;
1;
__END__
=head1 NAME
SOAP::WSDL::Deserializer::XSD - Deserializer SOAP messages into SOAP::WSDL::XSD::Typelib:: objects
=head1 DESCRIPTION
Default deserializer for SOAP::WSDL::Client and interface classes generated by
SOAP::WSDL. Converts SOAP messages to SOAP::WSDL::XSD::Typlib:: based objects.
Needs a class_resolver typemap either passed by the generated interface
or user-provided.
SOAP::WSDL::Deserializer classes implement the API described in
L<SOAP::WSDL::Factory::Deserializer>.
=head1 USAGE
Usually you don't need to do anything to use this package - it's the default
deserializer for SOAP::WSDL::Client and interface classes generated by
SOAP::WSDL.
Is you want to use the XSD serializer from SOAP::WSDL, set the outputtree()
property and provide a class_resolver.
=head1 METHODS
=head2 deserialize
Deserializes the message.
=head2 generate_fault
Generates a L<SOAP::WSDL::SOAP::Typelib::Fault11|SOAP::WSDL::SOAP::Typelib::Fault11>
object and returns it.
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: XSD.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Deserializer/XSD.pm $
=cut

View File

@@ -3,6 +3,8 @@ use strict;
use warnings;
use XML::Parser::Expat;
our $VERSION = '2.00_24';
sub new {
my ($class, $args) = @_;
my $self = {};
@@ -11,21 +13,21 @@ sub new {
}
sub parse {
eval {
eval {
$_[0]->_initialize( XML::Parser::Expat->new( Namespaces => 1 ) )->parse( $_[1] );
$_[0]->{ parser }->release();
};
$_[0]->{ parser }->xpcroak( $@ ) if $@;
return $_[0]->{ data };
return $_[0]->{ data };
}
sub parsefile {
eval {
$_[0]->_initialize( XML::Parser::Expat->new(Namespaces => 1) )->parsefile( $_[1] );
eval {
$_[0]->_initialize( XML::Parser::Expat->new(Namespaces => 1) )->parsefile( $_[1] );
$_[0]->{ parser }->release();
};
$_[0]->{ parser }->xpcroak( $@ ) if $@;
return $_[0]->{ data };
return $_[0]->{ data };
}
# SAX-like aliases

View File

@@ -4,55 +4,57 @@ use strict;
use warnings;
use base qw(SOAP::WSDL::Expat::Base);
our $VERSION = '2.00_24';
sub _initialize {
my ($self, $parser) = @_;
$self->{ parser } = $parser;
delete $self->{ data }; # remove potential old results
delete $self->{ data }; # remove potential old results
my $characters;
my $current = {};
my $list = []; # node list
my $current_part = q{}; # are we in header or body ?
$self->{ data } = $current;
# use "globals" for speed
my ($_element, $_method,
my ($_element, $_method,
$_class, $_parser, %_attrs) = ();
no strict qw(refs);
no strict qw(refs);
$parser->setHandlers(
Start => sub {
push @$list, $current;
#If our element exists and is a list ref, add to it
if ( exists $current->{ $_[1] }
&& ( ref ($current->{ $_[1] }) eq 'ARRAY')
) {
push @{ $current->{ $_[1] } }, {};
$current = $current->{ $_[1] }->[-1];
}
elsif ( exists $current->{ $_[1] } )
{
#If our element exists and is a list ref, add to it
if ( exists $current->{ $_[1] }
&& ( ref ($current->{ $_[1] }) eq 'ARRAY')
) {
push @{ $current->{ $_[1] } }, {};
$current = $current->{ $_[1] }->[-1];
}
elsif ( exists $current->{ $_[1] } )
{
$current->{ $_[1] } = [ $current->{ $_[1] }, {} ];
$current = $current->{ $_[1] }->[-1];
}
$current = $current->{ $_[1] }->[-1];
}
else {
$current->{ $_[1] } = {};
$current = $current->{ $_[1] };
}
return;
},
Char => sub {
$characters .= $_[1] if $_[1] !~m{ \A \s* \z}xms;
return;
},
End => sub {
End => sub {
$_element = $_[1];
# This one easily handles ignores for us, too...
# return if not ref $$list[-1];
if (length $characters) {
if (ref $list->[-1]->{ $_element } eq 'ARRAY') {
$list->[-1]->{ $_element }->[-1] = $characters ;
@@ -80,7 +82,7 @@ SOAP::WSDL::Expat::Message2Hash - Convert SOAP messages to perl hash refs
=head1 SYNOPSIS
my $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'My::Resolver'
class_resolver => 'My::Resolver'
});
$parser->parse( $xml );
my $obj = $parser->get_data();

View File

@@ -5,11 +5,13 @@ use warnings;
use SOAP::WSDL::XSD::Typelib::Builtin;
use base qw(SOAP::WSDL::Expat::Base);
our $VERSION = '2.00_24';
sub new {
my ($class, $args) = @_;
my $self = {
class_resolver => $args->{ class_resolver },
strict => exists $args->{ strict } ? $args->{ strict } : 1,
strict => exists $args->{ strict } ? $args->{ strict } : 1,
};
bless $self, $class;
return $self;
@@ -18,7 +20,7 @@ sub new {
sub class_resolver {
my $self = shift;
$self->{ class_resolver } = shift if @_;
return $self->{ class_resolver };
return $self->{ class_resolver };
}
sub _initialize {
@@ -27,30 +29,30 @@ sub _initialize {
delete $self->{ data }; # remove potential old results
delete $self->{ header };
my $characters;
#my @characters_from = ();
my $current = undef;
my $list = []; # node list
my $path = []; # current path
my $path = []; # current path
my $skip = 0; # skip elements
my $current_part = q{}; # are we in header or body ?
my $depth = 0;
my %content_check = $self->{strict}
my %content_check = $self->{strict}
? (
0 => sub {
die "Bad top node $_[1]" if $_[1] ne 'Envelope';
die "Bad namespace for SOAP envelope: " . $_[0]->recognized_string()
if $_[0]->namespace($_[1]) ne 'http://schemas.xmlsoap.org/soap/envelope/';
$depth++;
return;
return;
},
1 => sub {
$depth++;
if ($_[1] eq 'Body') {
if (exists $self->{ data }) { # there was header data
if (exists $self->{ data }) { # there was header data
$self->{ header } = $self->{ data };
delete $self->{ data };
$list = [];
@@ -58,37 +60,37 @@ sub _initialize {
undef $current;
}
}
return;
return;
}
)
)
: ();
my $char_handler = sub {
# push @characters_from, $_[1] if $_[1] =~m{ [^s] }xms;
$characters .= $_[1] if $_[1] =~m{ [^\s] }xms;
return;
};
# use "globals" for speed
my ($_prefix, $_method,
my ($_prefix, $_method,
$_class) = ();
no strict qw(refs);
no strict qw(refs);
$parser->setHandlers(
Start => sub {
Start => sub {
# my ($parser, $element, %_attrs) = @_;
# $depth = $parser->depth();
# call methods without using their parameter stack
# That's slightly faster than $content_check{ $depth }->()
# and we don't have to pass $_[1] to the method.
# Yup, that's dirty.
return &{$content_check{ $depth }} if exists $content_check{ $depth };
# Yup, that's dirty.
return &{$content_check{ $depth }} if exists $content_check{ $depth };
push @{ $path }, $_[1]; # step down in path
return if $skip; # skip inside __SKIP__
# resolve class of this element
$_class = $self->{ class_resolver }->get_class( $path )
or die "Cannot resolve class for "
@@ -96,66 +98,65 @@ sub _initialize {
if ($_class eq '__SKIP__') {
$skip = join('/', @{ $path });
$self->setHandlers( Char => undef );
$_[0]->setHandlers( Char => undef );
return;
}
push @$list, $current; # step down in tree ()remember current)
}
push @$list, $current; # step down in tree (remember current)
$characters = q(); # empty characters
#@characters_from = ();
# Check whether we have a builtin - we implement them as classes
# We could replace this with UNIVERSAL->isa() - but it's slow...
# match is a bit faster if the string does not match, but WAY slower
# if $class matches...
if (index $_class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
# match is a bit faster if the string does not match, but WAY slower
# if $class matches. We hope to match often...
if (index $_class, 'SOAP::WSDL::XSD::Typelib::Builtin', 0 < 0) {
# check wheter there is a non-empty ARRAY reference for $_class::ISA
# or a "new" method
# If not, require it - all classes required here MUST
# define new()
# This is not exactly the same as $class->can('new'), but it's way faster
# This is not exactly the same as $class->can('new'), but it's way faster
defined *{ "$_class\::new" }{ CODE }
or scalar @{ *{ "$_class\::ISA" }{ ARRAY } }
or eval "require $_class" ## no critic qw(ProhibitStringyEval)
or die $@;
or die $@;
}
$current = $_class->new({ @_[2..$#_] }); # set new current object
# remember top level element
exists $self->{ data }
or ($self->{ data } = $current);
exists $self->{ data }
or ($self->{ data } = $current);
$depth++;
return;
},
Char => $char_handler,
End => sub {
pop @{ $path }; # step up in path
if ($skip) {
return if $skip ne join '/', @{ $path }, $_[1];
$skip = 0;
$_[0]->setHandler( Char => $char_handler );
$_[0]->setHandlers( Char => $char_handler );
return;
}
$depth--;
# This one easily handles ignores for us, too...
return if not ref $list->[-1];
# set characters in current if we are a simple type
# we may have characters in complexTypes with simpleContent,
# too - maybe we should rely on the presence of characters ?
# may get a speedup by defining a ident method in anySimpleType
# may get a speedup by defining a ident method in anySimpleType
# and looking it up via exists &$class::ident;
# if ( $current->isa('SOAP::WSDL::XSD::Typelib::Builtin::anySimpleType') ) {
# $current->set_value( $characters );
# }
# currently doesn't work, as anyType does not implement value -
# currently doesn't work, as anyType does not implement value -
# maybe change ?
$current->set_value( $characters ) if (length $characters);
#$current->set_value( join @characters_from ) if (@characters_from);
@@ -166,7 +167,7 @@ sub _initialize {
#$_method = "add_$_localname";
$_method = "add_$_[1]";
$list->[-1]->$_method( $current );
$current = pop @$list; # step up in object hierarchy...
return;
}
@@ -174,7 +175,6 @@ sub _initialize {
return $parser;
}
sub get_header {
return $_[0]->{ header };
}
@@ -190,7 +190,7 @@ SOAP::WSDL::Expat::MessageParser - Convert SOAP messages to custom object trees
=head1 SYNOPSIS
my $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'My::Resolver'
class_resolver => 'My::Resolver'
});
$parser->parse( $xml );
my $obj = $parser->get_data();
@@ -205,8 +205,8 @@ See L<SOAP::WSDL::Manual::Parser> for details.
Sometimes there's unneccessary information transported in SOAP messages.
To skip XML nodes (including all child nodes), just edit the type map for
the message and set the type map entry to '__SKIP__'.
To skip XML nodes (including all child nodes), just edit the type map for
the message and set the type map entry to '__SKIP__'.
=head1 Bugs and Limitations
@@ -220,23 +220,22 @@ the message and set the type map entry to '__SKIP__'.
=back
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
Replace the whitespace by @ for E-Mail Address.
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
=head1 COPYING
This module may be used under the same terms as perl itself.
=head1 Repository information
$ID: $
$LastChangedDate: 2007-10-07 19:27:58 +0200 (Son, 07 Okt 2007) $
$LastChangedRevision: 313 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: MessageParser.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageParser.pm $
=cut

View File

@@ -6,6 +6,8 @@ use XML::Parser::Expat;
use SOAP::WSDL::Expat::MessageParser;
use base qw(SOAP::WSDL::Expat::MessageParser);
our $VERSION = '2.00_24';
sub parse_start {
my $self = shift;
$self->{ parser } = $_[0]->_initialize( XML::Parser::ExpatNB->new( Namespaces => 1 ) );
@@ -35,7 +37,7 @@ SOAP::WSDL::Expat::MessageStreamParser - Convert SOAP messages to custom object
my $lwp = LWP::UserAgent->new();
my $parser = SOAP::WSDL::Expat::MessageParser->new({
class_resolver => 'My::Resolver'
class_resolver => 'My::Resolver'
});
my $chunk_parser = $parser->init();
# process response while it comes in, trying to read 32k chunks.
@@ -54,23 +56,22 @@ See L<SOAP::WSDL::Manual::Parser> for details.
See SOAP::WSDL::Expat::MessageParser
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribte/modify it under
the same terms as perl itself
=head1 AUTHOR
Replace the whitespace by @ for E-Mail Address.
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
=head1 COPYING
This module may be used under the same terms as perl itself.
=head1 Repository information
$ID: $
$LastChangedDate: 2007-10-07 19:27:58 +0200 (Son, 07 Okt 2007) $
$LastChangedRevision: 313 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: MessageStreamParser.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Expat/MessageStreamParser.pm $
=cut

View File

@@ -11,12 +11,12 @@ sub _initialize {
# init object data
$self->{ parser } = $parser;
delete $self->{ data };
# setup local variables for keeping temp data
my $characters = undef;
my $current = undef;
my $list = []; # node list
# TODO skip non-XML Schema namespace tags
$parser->setHandlers(
Start => sub {
@@ -33,21 +33,21 @@ sub _initialize {
if ($action->{ type } eq 'CLASS') {
eval "require $action->{ class }";
croak $@ if ($@);
my $obj = $action->{ class }->new({ parent => $current })
->init( _fixup_attrs( $parser, %attrs ) );
if ($current) {
# inherit namespace, but don't override
$obj->set_targetNamespace( $current->get_targetNamespace() )
if not $obj->get_targetNamespace();
# push on parent's element/type list
my $method = "push_$localname";
no strict qw(refs);
$current->$method( $obj );
# remember element for stepping back
push @{ $list }, $current;
}
@@ -62,7 +62,7 @@ sub _initialize {
}
elsif ($action->{ type } eq 'METHOD') {
my $method = $action->{ method } || $localname;
no strict qw(refs);
# call method with
# - default value ($action->{ value } if defined,
@@ -74,26 +74,26 @@ sub _initialize {
? ref $action->{ value }
? @{ $action->{ value } }
: ($action->{ value })
: _fixup_attrs($parser, %attrs)
: _fixup_attrs($parser, %attrs)
);
}
return;
},
Char => sub { $characters .= $_[1]; return; },
End => sub {
End => sub {
my ($parser, $localname) = @_;
my $action = SOAP::WSDL::TypeLookup->lookup(
$parser->namespace( $localname ),
$localname
) || {};
return if not ($action->{ type });
if ( $action->{ type } eq 'CLASS' ) {
$current = pop @{ $list };
if ( $action->{ type } eq 'CLASS' ) {
$current = pop @{ $list };
}
elsif ($action->{ type } eq 'CONTENT' ) {
my $method = $action->{ method };
@@ -114,24 +114,24 @@ sub _initialize {
# make attrs SAX style
sub _fixup_attrs {
my ($parser, %attrs_of) = @_;
my @attrs_from = map { $_ =
my @attrs_from = map { $_ =
{
Name => $_,
Value => $attrs_of{ $_ },
LocalName => $_
}
Name => $_,
Value => $attrs_of{ $_ },
LocalName => $_
}
} keys %attrs_of;
# add xmlns: attrs. expat eats them.
push @attrs_from, map {
# ignore xmlns=FOO namespaces - must be XML schema
# add xmlns: attrs. expat eats them.
push @attrs_from, map {
# ignore xmlns=FOO namespaces - must be XML schema
# Other nodes should be ignored somewhere else
($_ eq '#default')
? ()
? ()
:
{
Name => "xmlns:$_",
{
Name => "xmlns:$_",
Value => $parser->expand_ns_prefix( $_ ),
LocalName => $_
}

View File

@@ -2,6 +2,8 @@ package SOAP::WSDL::Factory::Deserializer;
use strict;
use warnings;
our $VERSION = '2.00_24';
my %DESERIALIZER = (
'1.1' => 'SOAP::WSDL::Deserializer::XSD',
);
@@ -20,7 +22,7 @@ sub get_deserializer {
if not exists ($DESERIALIZER{ $args_of_ref->{ soap_version } });
# load module
eval "require $DESERIALIZER{ $args_of_ref->{ soap_version } }"
eval "require $DESERIALIZER{ $args_of_ref->{ soap_version } }"
or die "Cannot load serializer $DESERIALIZER{ $args_of_ref->{ soap_version } }", $@;
return $DESERIALIZER{ $args_of_ref->{ soap_version } }->new($args_of_ref);
@@ -51,7 +53,7 @@ SOAP::WSDL::Factory::Deserializer - Factory for retrieving Deserializer objects
=head1 DESCRIPTION
SOAP::WSDL::Factory::Deserializer serves as factory for retrieving
SOAP::WSDL::Factory::Deserializer serves as factory for retrieving
deserializer objects for SOAP::WSDL.
The actual work is done by specific deserializer classes.
@@ -64,7 +66,7 @@ SOAP::WSDL::Deserializer tries to load one of the following classes:
=back
By default, L<SOAP::WSDL::Deserializer::XSD|SOAP::WSDL::Deserializer::XSD>
By default, L<SOAP::WSDL::Deserializer::XSD|SOAP::WSDL::Deserializer::XSD>
is registered for SOAP1.1 messages.
=head1 METHODS
@@ -85,25 +87,25 @@ Deserializer classes may register with SOAP::WSDL::Factory::Deserializer.
=head2 Registering a deserializer
Registering a deserializer class with SOAP::WSDL::Factory::Deserializer
is done by executing the following code where $version is the SOAP version
Registering a deserializer class with SOAP::WSDL::Factory::Deserializer
is done by executing the following code where $version is the SOAP version
the class should be used for, and $class is the class name.
SOAP::WSDL::Factory::Deserializer->register( $version, $class);
To auto-register your transport class on loading, execute register()
To auto-register your transport class on loading, execute register()
in your tranport class (see L<SYNOPSIS|SYNOPSIS> above).
=head2 Deserializer package layout
Deserializer modules must be named equal to the deserializer class they
Deserializer modules must be named equal to the deserializer class they
contain. There can only be one deserializer class per deserializer module.
=head2 Methods to implement
Deserializer classes must implement the following methods:
=over
=over
=item * new
@@ -111,31 +113,31 @@ Constructor.
=item * deserialize
Deserialize data from XML to arbitrary formats.
Deserialize data from XML to arbitrary formats.
deserialize() must return a fault indicating that deserializing failed if
deserialize() must return a fault indicating that deserializing failed if
any error is encountered during the process of deserializing the XML message.
The following positional parameters are passed to the deserialize method:
$content - the xml message
$content - the xml message
=item * generate_fault
Generate a fault in the supported format. The following named parameters are
Generate a fault in the supported format. The following named parameters are
passed as a single hash ref:
code - The fault code, e.g. 'soap:Server' or the like
role - The fault role (actor in SOAP1.1)
role - The fault role (actor in SOAP1.1)
message - The fault message (faultstring in SOAP1.1)
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribte/modify it under
the same terms as perl itself
=head1 AUTHOR

View File

@@ -2,7 +2,7 @@ package SOAP::WSDL::Factory::Generator;
use strict;
use warnings;
our $VERSION='2.00_18';
our $VERSION='2.00_24';
my %GENERATOR = (
'XSD' => 'SOAP::WSDL::Generator::Template::XSD',
@@ -19,13 +19,13 @@ sub get_generator {
# sanity check
# die "no generator registered for generation method $args_of_ref->{ type }"
#
my $generator_class = (exists ($GENERATOR{ $args_of_ref->{ type } }))
#
my $generator_class = (exists ($GENERATOR{ $args_of_ref->{ type } }))
? $GENERATOR{ $args_of_ref->{ type } }
: $args_of_ref->{ type };
# load module
eval "require $generator_class"
eval "require $generator_class"
or die "Cannot load generator $generator_class", $@;
return $generator_class->new();
@@ -55,7 +55,7 @@ SOAP::WSDL::Factory:Generator - Factory for retrieving generator objects
=head1 DESCRIPTION
SOAP::WSDL::Factory::Generator serves as factory for retrieving
SOAP::WSDL::Factory::Generator serves as factory for retrieving
generator objects for SOAP::WSDL.
The actual work is done by specific generator classes.
@@ -86,25 +86,25 @@ Returns an object of the generator class for this endpoint.
Generator classes may register with SOAP::WSDL::Factory::Generator.
Registering a generator class with SOAP::WSDL::Factory::Generator is done
by executing the following code where $version is the SOAP version the
Registering a generator class with SOAP::WSDL::Factory::Generator is done
by executing the following code where $version is the SOAP version the
class should be used for, and $class is the class name.
SOAP::WSDL::Factory::Generator->register( $version, $class);
To auto-register your transport class on loading, execute register() in
To auto-register your transport class on loading, execute register() in
your generator class (see L<SYNOPSIS|SYNOPSIS> above).
=head2 Generator package layout
Generator modules must be named equal to the generator class they contain.
Generator modules must be named equal to the generator class they contain.
There can only be one generator class per generator module.
=head2 Methods to implement
Generator classes must implement the following methods:
=over
=over
=item * new
@@ -116,7 +116,7 @@ Generate SOAP interface
=back
Generators may implements one or more of the following configuration
Generators may implements one or more of the following configuration
methods. All of them are tried via can() by wsdl2perl.
=over
@@ -151,12 +151,12 @@ Set user-defined typemap snippet
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright (c) 2004-2007 Martin Kutter.
Copyright 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under the same
terms as perl itself
This file is part of SOAP-WSDL. You may distribte/modify it under
the same terms as perl itself
=head1 AUTHOR
@@ -164,9 +164,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 302 $
$Rev: 176 $
$LastChangedBy: kutterma $
$Id: Generator.pm 302 2007-09-30 19:25:25Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Generator.pm $
$Id: Serializer.pm 176 2007-08-31 15:28:29Z kutterma $
$HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
=cut

View File

@@ -2,7 +2,7 @@ package SOAP::WSDL::Factory::Serializer;
use strict;
use warnings;
our $VERSION='2.00_17';
our $VERSION='2.00_24';
my %SERIALIZER = (
'1.1' => 'SOAP::WSDL::Serializer::XSD',
@@ -22,7 +22,7 @@ sub get_serializer {
if not exists ($SERIALIZER{ $args_of_ref->{ soap_version } });
# load module
eval "require $SERIALIZER{ $args_of_ref->{ soap_version } }"
eval "require $SERIALIZER{ $args_of_ref->{ soap_version } }"
or die "Cannot load serializer $SERIALIZER{ $args_of_ref->{ soap_version } }", $@;
return $SERIALIZER{ $args_of_ref->{ soap_version } }->new();
@@ -52,7 +52,7 @@ SOAP::WSDL::Factory::Serializer - Factory for retrieving serializer objects
=head1 DESCRIPTION
SOAP::WSDL::Factory::Serializer serves as factory for retrieving
SOAP::WSDL::Factory::Serializer serves as factory for retrieving
serializer objects for SOAP::WSDL.
The actual work is done by specific serializer classes.
@@ -83,30 +83,30 @@ Returns an object of the serializer class for this endpoint.
Serializer classes may register with SOAP::WSDL::Factory::Serializer.
Serializer objects may also be passed directly to SOAP::WSDL::Client by
using the set_serializer method. Note that serializers objects set via
SOAP::WSDL::Client's set_serializer method are discarded when the SOAP
Serializer objects may also be passed directly to SOAP::WSDL::Client by
using the set_serializer method. Note that serializers objects set via
SOAP::WSDL::Client's set_serializer method are discarded when the SOAP
version is changed via set_soap_version.
Registering a serializer class with SOAP::WSDL::Factory::Serializer is done
by executing the following code where $version is the SOAP version the
Registering a serializer class with SOAP::WSDL::Factory::Serializer is done
by executing the following code where $version is the SOAP version the
class should be used for, and $class is the class name.
SOAP::WSDL::Factory::Serializer->register( $version, $class);
To auto-register your transport class on loading, execute register() in
To auto-register your transport class on loading, execute register() in
your tranport class (see L</SYNOPSIS> above).
=head2 Serializer package layout
Serializer modules must be named equal to the serializer class they contain.
Serializer modules must be named equal to the serializer class they contain.
There can only be one serializer class per serializer module.
=head2 Methods to implement
Serializer classes must implement the following methods:
=over
=over
=item * new
@@ -114,7 +114,7 @@ Constructor.
=item * serialize
Serializes data to XML. The following named parameters are passed to the
Serializes data to XML. The following named parameters are passed to the
serialize method in a anonymous hash ref:
{
@@ -125,12 +125,12 @@ serialize method in a anonymous hash ref:
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright 2004-2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
@@ -138,9 +138,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 329 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Serializer.pm 329 2007-10-18 19:42:09Z kutterma $
$Id: Serializer.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Serializer.pm $
=cut

View File

@@ -16,12 +16,12 @@ my %SOAP_LITE_TRANSPORT_OF = (
mailto => 'SOAP::Transport::MAILTO',
'local' => 'SOAP::Transport::LOCAL',
jabber => 'SOAP::Transport::JABBER',
mq => 'SOAP::Transport::MQ',
mq => 'SOAP::Transport::MQ',
);
my %SOAP_WSDL_TRANSPORT_OF = (
http => 'SOAP::WSDL::Transport::HTTP',
https => 'SOAP::WSDL::Transport::HTTP',
https => 'SOAP::WSDL::Transport::HTTP',
);
# class methods only
@@ -35,16 +35,16 @@ sub get_transport {
my ($class, $scheme, %attrs) = @_;
$scheme =~s{ \A ([^\:]+) \: .+ }{$1}smx;
if ($registered_transport_of{ $scheme }) {
eval "require $registered_transport_of{ $scheme }"
or die "Cannot load transport class $registered_transport_of{ $scheme } : $@";
# try "foo::Client" class first - SOAP::Tranport always requires
# try "foo::Client" class first - SOAP::Tranport always requires
# a package withoug the ::Client appended, and then
# instantiates a ::Client object...
# ... pretty weird ...
# ... must be from some time when the max number of files was a
# ... must be from some time when the max number of files was a
# sparse resource ...
# ... but we've decided to mimic SOAP::Lite...
@@ -68,7 +68,7 @@ sub get_transport {
}
if (exists $SOAP_WSDL_TRANSPORT_OF{ $scheme }) {
eval "require $SOAP_WSDL_TRANSPORT_OF{ $scheme }"
eval "require $SOAP_WSDL_TRANSPORT_OF{ $scheme }"
or die "Cannot load transport class $SOAP_WSDL_TRANSPORT_OF{ $scheme } : $@";
return $SOAP_WSDL_TRANSPORT_OF{ $scheme }->new( %attrs );
}
@@ -100,14 +100,14 @@ SOAP::WSDL::Factory::Transport - Factory for retrieving transport objects
=head1 DESCRIPTION
SOAP::WSDL::Transport serves as factory for retrieving transport objects for
SOAP::WSDL::Transport serves as factory for retrieving transport objects for
SOAP::WSDL.
The actual work is done by specific transport classes.
SOAP::WSDL::Transport tries to load one of the following classes:
=over
=over
=item * the class registered for the scheme via register()
@@ -129,7 +129,7 @@ Globally registers a class for use as transport class.
$trans->proxy('http://soap-wsdl.sourceforge.net');
Sets the proxy (endpoint).
Sets the proxy (endpoint).
Returns the transport for this protocol.
@@ -145,34 +145,34 @@ Gets the current transport object.
=head2 Registering a transport class
Transport classes must be registered with SOAP::WSDL::Factory::Transport.
Transport classes must be registered with SOAP::WSDL::Factory::Transport.
This is done by executing the following code where $scheme is the URL scheme
the class should be used for, and $module is the class' module name.
This is done by executing the following code where $scheme is the URL scheme
the class should be used for, and $module is the class' module name.
SOAP::WSDL::Factory::Transport->register( $scheme, $module);
To auto-register your transport class on loading, execute register() in your
To auto-register your transport class on loading, execute register() in your
tranport class (see L<SYNOPSIS|SYNOPSIS> above).
Multiple protocols ore multiple classes are registered by multiple calls to
Multiple protocols ore multiple classes are registered by multiple calls to
register().
=head2 Transport plugin package layout
You may only use transport classes whose name is either
You may only use transport classes whose name is either
the module name or the module name with '::Client' appended.
=head2 Methods to implement
Transport classes must implement the interface required for SOAP::Lite
transport classes (see L<SOAP::Lite::Transport> for details,
Transport classes must implement the interface required for SOAP::Lite
transport classes (see L<SOAP::Lite::Transport> for details,
L<SOAP::WSDL::Transport::HTTP|SOAP::WSDL::Transport::HTTP> for an example).
To provide this interface, transport modules must implement the following
To provide this interface, transport modules must implement the following
methods:
=over
=over
=item * new
@@ -198,12 +198,12 @@ Returns true after a send_receive was successful, false if it was not.
=back
SOAP::Lite requires transport modules to pack client and server
SOAP::Lite requires transport modules to pack client and server
classes in one file, and to follow this naming scheme:
Module name:
Module name:
"SOAP::Transport::" . uc($scheme)
Client class (additional package in module):
"SOAP::Transport::" . uc($scheme) . "::Client"
@@ -214,20 +214,20 @@ SOAP::WSDL does not require you to follow these restrictions.
There is only one restriction in SOAP::WSDL:
You may only use transport classes whose name is either the module name or
You may only use transport classes whose name is either the module name or
the module name with '::Client' appended.
SOAP::WSDL will try to instantiate an object of your transport class with
SOAP::WSDL will try to instantiate an object of your transport class with
'::Client' appended to allow using transport classes written for SOAP::Lite.
This may lead to errors when a different module with the name of your
This may lead to errors when a different module with the name of your
transport module suffixed with ::Client is also loaded.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright 2004-2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
@@ -236,9 +236,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 304 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Transport.pm 304 2007-10-02 20:07:21Z kutterma $
$Id: Transport.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Factory/Transport.pm $
=cut

View File

@@ -23,15 +23,15 @@ sub START {
sub _process :PROTECTED {
my ($self, $template, $arg_ref, $output) = @_;
my $ident = ident $self;
my $tt = $tt_of{$ident} ||= Template->new(
my $tt = $tt_of{$ident} ||= Template->new(
DEBUG => 1,
EVAL_PERL => $EVAL_PERL_of{ $ident },
RECURSION => $RECURSION_of{ $ident },
INCLUDE_PATH => $INCLUDE_PATH_of{ $ident },
OUTPUT_PATH => $OUTPUT_PATH_of{ $ident },
);
$tt->process( $template,
{
$tt->process( $template,
{
definitions => $self->get_definitions,
interface_prefix => $self->get_interface_prefix,
type_prefix => $self->get_type_prefix,
@@ -40,10 +40,9 @@ sub _process :PROTECTED {
element_prefix => $self->get_element_prefix,
NO_POD => delete $arg_ref->{ NO_POD } ? 1 : 0 ,
%{ $arg_ref }
},
},
$output)
or die $INCLUDE_PATH_of{ $ident }, '\\', $template, ' ', $tt->error();
}
1;

View File

@@ -18,23 +18,23 @@ sub BUILD {
$self->set_RECURSION(1);
$self->set_INCLUDE_PATH( exists $arg_ref->{INCLUDE_PATH}
? $arg_ref->{INCLUDE_PATH}
: do {
# ignore uninitialized warnings - File::Spec warns about
: do {
# ignore uninitialized warnings - File::Spec warns about
# uninitialized values, probably because we have no filename
local $SIG{__WARN__} = sub {
return if ($_[0]=~m{\buninitialized\b});
CORE::warn @_;
};
# makeup path for the OS we're running on
my ($volume, $dir, $file) = File::Spec->splitpath(
my ($volume, $dir, $file) = File::Spec->splitpath(
File::Spec->rel2abs( dirname __FILE__ )
);
$dir = File::Spec->catdir($dir, $file, 'XSD');
# return path put together...
my $path = File::Spec->catpath( $volume, $dir );
# Fixup path for windows - / works fine, \ does
# Fixup path for windows - / works fine, \ does
# not...
if ( eval { &Win32::BuildNumber } ) {
$path =~s{\\}{/}g;
@@ -54,16 +54,13 @@ sub generate {
sub generate_typelib {
my ($self) = @_;
# $output_of{ ident $self } = "";
my @schema = @{ $self->get_definitions()->first_types()->get_schema() };
for my $type (map { @{ $_->get_type() } , @{ $_->get_element() } } @schema[1..$#schema] ) {
$type->_accept( $self );
}
# return $output_of{ ident $self };
return;
}
sub generate_interface {
@@ -72,23 +69,23 @@ sub generate_interface {
my $arg_ref = shift;
my $tt = $self->get_tt();
for my $service (@{ $self->get_definitions->get_service }) {
for my $port (@{ $service->get_port() }) {
for my $port (@{ $service->get_port() }) {
# Skip ports without (known) address
next if not $port->first_address;
next if not $port->first_address->isa('SOAP::WSDL::SOAP::Address');
my $port_name = $port->get_name;
$port_name =~s{ \A .+\. }{}xms;
my $output = $arg_ref->{ output }
? $arg_ref->{ output }
: $self->_generate_filename(
$self->get_interface_prefix(),
$service->get_name(),
my $output = $arg_ref->{ output }
? $arg_ref->{ output }
: $self->_generate_filename(
$self->get_interface_prefix(),
$service->get_name(),
$port_name,
);
);
print "Creating interface class $output\n";
$self->_process('Interface.tt',
$self->_process('Interface.tt',
{
service => $service,
port => $port,
@@ -101,7 +98,6 @@ sub generate_interface {
sub generate_typemap {
my ($self, $arg_ref) = @_;
my $visitor = SOAP::WSDL::Generator::Visitor::Typemap->new({
type_prefix => $self->get_type_prefix(),
element_prefix => $self->get_element_prefix(),
@@ -112,17 +108,16 @@ sub generate_typemap {
'Fault/faultactor' => 'SOAP::WSDL::XSD::Typelib::Builtin::TOKEN',
'Fault/faultstring' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
%{ $typemap_of{ident $self }},
%{ $typemap_of{ident $self }},
}
});
for my $service (@{ $self->get_definitions->get_service }) {
$visitor->visit_Service( $service );
my $output = $arg_ref->{ output }
? $arg_ref->{ output }
: $self->_generate_filename( $self->get_typemap_prefix(), $service->get_name() );
my $output = $arg_ref->{ output }
? $arg_ref->{ output }
: $self->_generate_filename( $self->get_typemap_prefix(), $service->get_name() );
print "Creating typemap class $output\n";
$self->_process('Typemap.tt',
$self->_process('Typemap.tt',
{
service => $service,
typemap => $visitor->get_typemap(),
@@ -142,7 +137,7 @@ sub _generate_filename :PRIVATE {
sub visit_XSD_Element {
my ($self, $element) = @_;
my $output = defined $output_of{ ident $self }
my $output = defined $output_of{ ident $self }
? $output_of{ ident $self }
: $self->_generate_filename( $self->get_element_prefix(), $element->get_name() );
$self->_process('element.tt', { element => $element } , $output);
@@ -150,7 +145,7 @@ sub visit_XSD_Element {
sub visit_XSD_SimpleType {
my ($self, $type) = @_;
my $output = defined $output_of{ ident $self }
my $output = defined $output_of{ ident $self }
? $output_of{ ident $self }
: $self->_generate_filename( $self->get_type_prefix(), $type->get_name() );
$self->_process('simpleType.tt', { simpleType => $type } , $output);
@@ -158,7 +153,7 @@ sub visit_XSD_SimpleType {
sub visit_XSD_ComplexType {
my ($self, $type) = @_;
my $output = defined $output_of{ ident $self }
my $output = defined $output_of{ ident $self }
? $output_of{ ident $self }
: $self->_generate_filename( $self->get_type_prefix(), $type->get_name() );
$self->_process('complexType.tt', { complexType => $type } , $output);

View File

@@ -2,11 +2,12 @@ package [% interface_prefix %]::[% service.get_name.replace('\.', '::') %]::[% p
use strict;
use warnings;
use Class::Std::Storable;
use Scalar::Util qw(blessed);
use base qw(SOAP::WSDL::Client::Base);
# only load if it hasn't been loaded before
require [% typemap_prefix %]::[% service.get_name.replace('\.', '::') %]
if not [% typemap_prefix %]::[% service.get_name.replace('\.', '::') %]->can('get_class');
if not [% typemap_prefix %]::[% service.get_name.replace('\.', '::') %]->can('get_class');
sub START {
$_[0]->set_proxy('[% port.first_address.get_location %]') if not $_[2]->{proxy};
@@ -18,6 +19,7 @@ sub START {
FOREACH operation = binding.get_operation;
%][% INCLUDE Interface/Operation.tt %]
[%
END;
%]
@@ -32,11 +34,22 @@ __END__
=head1 NAME
[% interface_prefix %]::[% service.get_name %]::[% port.get_name %] - SOAP Interface for the [% service.get_name %] Web Service
[% interface_prefix %]::[% service.get_name.replace('\.', '::') %]::[% port.get_name.replace('\.', '::') %] - SOAP Interface for the [% service.get_name %] Web Service
=head1 SYNOPSIS
use [% interface_prefix %]::[% service.get_name.replace('\.', '::') %]::[% port.get_name.replace('\.', '::') %];
my $interface = [% interface_prefix %]::[% service.get_name.replace('\.', '::') %]::[% port.get_name.replace('\.', '::') %]->new();
my $response;
[% FOREACH operation = binding.get_operation;
%] $response = $interface->[% operation.get_name %]();
[% END %]
=head1 DESCRIPTION
SOAP Interface for the [% service.get_name %] web service
SOAP Interface for the [% service.get_name %] web service
located at [% port.first_address.get_location %].
=head1 SERVICE [% service.get_name %]
@@ -64,7 +77,7 @@ All arguments are forwarded to L<SOAP::WSDL::Client|SOAP::WSDL::Client>.
[% FOREACH operation = binding.get_operation;
%][% INCLUDE Interface/POD/Operation.tt %]
[% END %]
[% END %]
=head1 AUTHOR

View File

@@ -11,54 +11,53 @@
my $element_prefix = $stash->{ element_prefix };
my @body_part_from = split m{\s}, $item->get_parts;
my @parts;
if (@body_part_from) {
@parts = map {
my $part = $_;
(grep {
my ($ns, $lname) = $def->expand( $_ );
($lname eq $part->get_name)
} @body_part_from
)
? do {
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
$element_prefix . '::' . $name;
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
$type_prefix . '::' . $name;
}
: die "input must have either type or element"
}
: ()
} @{ $part_from };
}
else {
@parts = map {
my $part = $_;
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
"$element_prefix\::$name"
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
"$type_prefix\::$name"
}
: die "input must have either type or element";
} @{ $part_from };
my @parts;
if (@body_part_from) {
@parts = map {
my $part = $_;
(grep {
my ($ns, $lname) = $def->expand( $_ );
($lname eq $part->get_name)
} @body_part_from
)
? do {
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
$element_prefix . '::' . $name;
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
$type_prefix . '::' . $name;
}
: die "input must have either type or element"
}
: ()
} @{ $part_from };
}
else {
@parts = map {
my $part = $_;
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
"$element_prefix\::$name"
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
"$type_prefix\::$name"
}
: die "input must have either type or element";
} @{ $part_from };
}
$stash->{ parts } = \@parts;
[% END;
%]
[% END %]
'use' => '[% item.get_use %]',
namespace => '[% item.get_namespace %]',
encodingStyle => '[% item.get_encodingStyle %]',

View File

@@ -1,8 +1,8 @@
[%
RETURN IF NOT item;
message_name = item.get_message;
IF NOT message_name;
THROW BAD_WSDL "missing <message> attribute in header for operation ${operation.get_name}";
IF NOT message_name;
THROW BAD_WSDL "missing <message> attribute in header for operation ${operation.get_name}";
END;
message = definitions.find_message( item.expand( message_name ) );
PERL %]
@@ -13,22 +13,22 @@
my $element_prefix = $stash->{ element_prefix };
my ($ns, $lname) = $def->expand( $item->get_part() );
my ($part) = grep {
$_->get_name eq $lname
&& $_->get_targetNamespace eq $ns } @{ $message->get_part( ) };
$_->get_name eq $lname
&& $_->get_targetNamespace eq $ns } @{ $message->get_part( ) };
my $part_class = do {
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
$element_prefix . '::' . $name;
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
$type_prefix . '::' . $name;
}
: die "input must have either type or element"
};
my $name;
($name = $part->get_element)
? do {
$name =~s{ ^[^:]+: }{}xms;
$element_prefix . '::' . $name;
}
: ($name = $part->get_type)
? do {
$name =~s{ ^[^:]+: }{}xms;
$type_prefix . '::' . $name;
}
: die "input must have either type or element"
};
$stash->{ part_class } = $part_class;
[% END;
%]

View File

@@ -1,10 +1,11 @@
sub [% operation.get_name %] {
my ($self, $body, $header) = @_;
die "[% operation.get_name %] must be called as object method (\$self is <$self>)" if not blessed($self);
return $self->SUPER::call({
operation => '[% operation.get_name %]',
operation => '[% operation.get_name %]',
soap_action => '[% operation.first_operation.get_soapAction %]',
style => '[% operation.get_style || binding.get_style %]',
body => {
body => {
[% INCLUDE Interface/Body.tt( item = operation.first_input.first_body ); %]
},
header => {

View File

@@ -1,13 +1,13 @@
[% INDENT; %][% element.get_name %] => [%-
IF (element.get_ref);
element = element.get_ref();
END;
IF (type_name = element.get_type);
IF (element.get_ref);
element = element.get_ref();
END;
IF (type_name = element.get_type);
INCLUDE Interface/POD/Type.tt(type = definitions.first_types.find_type( element.expand(type_name) ) );
ELSIF (type = element.first_complexType);
INCLUDE Interface/POD/Type.tt(type = type );
ELSIF (type = element.first_simpleType);
INCLUDE Interface/POD/Type.tt(type = type );
END;
END;
%]

View File

@@ -1,9 +1,9 @@
[%
message_name = port_op.first_input.get_message();
# message_name;
# message_name;
part_from = definitions.find_message( port_op.first_input.expand( message_name ) ).get_part;
FOREACH part = part_from;
INCLUDE Interface/POD/Part.tt(part = part);
INCLUDE Interface/POD/Part.tt(part = part);
END;
%]

View File

@@ -1,7 +1,7 @@
[% element = definitions.first_types.find_element( part.expand( part.get_element ) );
#element.get_name();
#element;
#STOP;
type = element.first_complexType || element.first_simpleType || definitions.first_types.find_type(
element.expand( element.get_type ) );
INCLUDE Interface/POD/Type.tt;%],
#element.get_name();
#element;
#STOP;
type = element.first_complexType || element.first_simpleType || definitions.first_types.find_type(
element.expand( element.get_type ) );
INCLUDE Interface/POD/Type.tt;%],

View File

@@ -1,7 +1,7 @@
[%- indent = ' ';
IF type.isa('SOAP::WSDL::XSD::ComplexType');
INCLUDE complexType/POD/structure.tt(complexType = type);
INCLUDE complexType/POD/structure.tt(complexType = type);
ELSE;
INCLUDE simpleType/POD/structure.tt(simpleType = type);
INCLUDE simpleType/POD/structure.tt(simpleType = type);
END;
indent.replace('\s{2}$',''); %]

View File

@@ -1,7 +1,7 @@
Method synopsis is displayed with hash refs as parameters.
Method synopsis is displayed with hash refs as parameters.
The commented class names in the method's parameters denote that objects
The commented class names in the method's parameters denote that objects
of the corresponding class can be passed instead of the marked hash ref.
You may pass any combination of objects, hash and list refs to these
You may pass any combination of objects, hash and list refs to these
methods, as long as you meet the structure.

View File

@@ -4,7 +4,7 @@ use warnings;
our [% USE Dumper(varname = 'typemap_'); Dumper.dump( typemap ) %];
sub get_class {
sub get_class {
my $name = join '/', @{ $_[1] };
exists $typemap_1->{ $name } or die "Cannot resolve $name via " . __PACKAGE__;
return $typemap_1->{ $name };

View File

@@ -1,6 +1,6 @@
[% type_name = node.expand( type );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
[% type_name = node.expand( type );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END -%]
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END -%]

View File

@@ -2,8 +2,8 @@ package [% type_prefix %]::[% complexType.get_name %];
use strict;
use warnings;
[% INCLUDE complexType/contentModel.tt %]
[%#
# Don't include any perl source here - there may be sub-packages...
[%#
# Don't include any perl source here - there may be sub-packages...
#-%]
1;
@@ -21,7 +21,7 @@ Perl data type class for the XML Schema defined complextype
=head2 PROPERTIES
The following properties may be accessed using get_PROPERTY / set_PROPERTY
The following properties may be accessed using get_PROPERTY / set_PROPERTY
methods:
[% FOREACH element = complexType.get_element -%]

View File

@@ -1,9 +1,9 @@
[% IF (complexType.get_variety == 'restriction');
INCLUDE complexType/POD/restriction.tt(complexType = complexType);
INCLUDE complexType/POD/restriction.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'sequence');
THROW NOT_IMPLEMENTED, "${ complexType.get_name } - complexType complexContent extension not implemented yet";
THROW NOT_IMPLEMENTED, "${ complexType.get_name } - complexType complexContent extension not implemented yet";
ELSE;
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
END;
%]

View File

@@ -1,13 +1,13 @@
[% IF (complexType.get_variety == 'all');
INCLUDE complexType/POD/all.tt(complexType = complexType);
INCLUDE complexType/POD/all.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'sequence');
INCLUDE complexType/POD/all.tt(complexType = complexType);
INCLUDE complexType/POD/all.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'group');
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
ELSIF (complexType.get_variety == 'choice');
INCLUDE complexType/POD/choice.tt(complexType = complexType);
INCLUDE complexType/POD/choice.tt(complexType = complexType);
ELSIF (complexType.get_contentModel == 'simpleContent');
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
ELSIF (complexType.get_contentModel == 'complexContent');
INCLUDE complexType/POD/complexContent.tt(complexType = complexType);
END %]
INCLUDE complexType/POD/complexContent.tt(complexType = complexType);
END %],

View File

@@ -2,8 +2,8 @@ use Class::Std::Storable;
use base qw(SOAP::WSDL::XSD::Typelib::ComplexType);
{ # BLOCK to scope variables
[%
atomic_types = [];
[%
atomic_types = {};
FOREACH element = complexType.get_element %]
my %[% element.get_name %]_of :ATTR(:get<[% element.get_name %]>);
@@ -14,30 +14,30 @@ __PACKAGE__->_factory(
[% element.get_name -%]
[% END %]
) ],
{
{
[% FOREACH element = complexType.get_element -%]
[% element.get_name %] => \%[% element.get_name %]_of,
[% END -%]
[% element.get_name %] => \%[% element.get_name %]_of,
[% END -%]
},
{
[% FOREACH element = complexType.get_element;
IF (type = element.get_type);
element_type = complexType.expand( type );
IF (element_type.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
IF (type = element.get_type);
element_type = complexType.expand( type );
IF (element_type.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
[% element.get_name %] => 'SOAP::WSDL::XSD::Typelib::Builtin::[% element_type.1 %]',
[% ELSE -%]
[% ELSE -%]
[% element.get_name %] => '[% type_prefix %]::[% element_type.1 %]',
[% END;
ELSE;
IF (element.first_simpleType);
atomic_types.push( element.first_simpleType );
ELSIF (element.first_simpleType);
atomic_types.push( element.first_simpleType );
ELSE;
THROW NOT_IMPLEMENTED , "atomic types in complexType elements not supported yet";
END; %]
[% element.get_name %] => '[% type_prefix %]::[% complexType.get_name %]::_[% element.get_name %]',
[% END;
[% END;
ELSE;
IF (element.first_simpleType);
atomic_types.${ element.get_name } = element.first_simpleType;
ELSIF (element.first_complexType);
atomic_types.${ element.get_name } = element.first_complexType;
ELSE;
THROW NOT_IMPLEMENTED , "Neither simple nor complex atomic type - don't know what to do with it";
END; %]
[% element.get_name %] => '[% type_prefix %]::[% complexType.get_name %]::_[% element.get_name %]',
[% END;
END -%]
}
);

View File

@@ -1,17 +1,17 @@
[% FOREACH type = atomic_types; %]
[% FOREACH type IN atomic_types; %]
package [% type_prefix %]::[% complexType.get_name %]::_[% element.get_name %];
package [% type_prefix %]::[% complexType.get_name %]::_[% type.key %];
use strict;
use warnings;
{
[% IF ( type.isa('SOAP::WSDL::XSD::ComplexType') );
INCLUDE complexType/contentModel.tt(complexType = type );
ELSIF ( type.isa('SOAP::WSDL::XSD::SimpleType') );
INCLUDE simpleType/contentModel.tt(simpleType = type );
ELSE;
PERL; %] die $stash->{ type }->_DUMP [% END;
THROW UNKNOWN, "neither complex nor simple type - don't know what to do";
[% IF ( type.value.isa('SOAP::WSDL::XSD::ComplexType') );
INCLUDE complexType/contentModel.tt(complexType = type.value );
ELSIF ( type.value.isa('SOAP::WSDL::XSD::SimpleType') );
INCLUDE simpleType/contentModel.tt(simpleType = type.value );
ELSE;
PERL; %] die $stash->{ type } [% END;
THROW UNKNOWN, "neither complex nor simple type - don't know what to do";
END
%]
}

View File

@@ -1,8 +1,8 @@
[% IF (complexType.get_variety == 'restriction');
INCLUDE complexType/restriction.tt(complexType = complexType);
INCLUDE complexType/restriction.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'sequence');
INCLUDE complexType/extension.tt(complexType = complexType);
INCLUDE complexType/extension.tt(complexType = complexType);
ELSE;
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
THROW UNKNOWN, "unknown variety ${ complexType.get_variety }";
END;
%]

View File

@@ -1,7 +1,7 @@
[% IF (complexType.get_contentModel == 'simpleContent');
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType simpleContent not implemented yet";
ELSIF (complexType.get_contentModel == 'complexContent');
INCLUDE complexType/complexContent.tt(complexType = complexType);
INCLUDE complexType/complexContent.tt(complexType = complexType);
ELSE;
INCLUDE complexType/variety.tt(complexType = complexType);
INCLUDE complexType/variety.tt(complexType = complexType);
END %]

View File

@@ -9,14 +9,14 @@ element_from = complexType.get_element;
# Sanity check: All original elements must be noted first
#
FOREACH element = base_type.get_element;
IF element_from.${ loop.index }.get_name != element.get_name;
THROW WSDL "${element.get_name} not found at position ${ loop.index } in extension type ${ complexType.get_name }";
END;
IF element_from.${ loop.index }.get_name != element.get_name;
THROW WSDL "${element.get_name} not found at position ${ loop.index } in extension type ${ complexType.get_name }";
END;
END;
-%]
use base qw([% type_prefix %]::[% base_name.1.replace('\.', '::') %]);
use base qw([% type_prefix %]::[% base_name.1.replace('\.', '::') %]);
[%
INCLUDE complexType/variety.tt(complexType = complexType);

View File

@@ -1,8 +1,8 @@
[% IF (base=complexType.get_base);
base_name=complexType.expand(base);
base_name=complexType.expand(base);
-%]
use base qw([% type_prefix %]::[% base_name.1.replace('\.', '::') %]);
[%
use base qw([% type_prefix %]::[% base_name.1.replace('\.', '::') %]);
[%
ELSE;
THROW NOT_IMPLEMENTED, "restriction without base not supported";
THROW NOT_IMPLEMENTED, "restriction without base not supported";
END %]

View File

@@ -1,15 +1,15 @@
[%
IF (complexType.get_variety == 'all');
INCLUDE complexType/all.tt(complexType = complexType);
INCLUDE complexType/all.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'sequence');
INCLUDE complexType/all.tt(complexType = complexType);
INCLUDE complexType/all.tt(complexType = complexType);
ELSIF (complexType.get_variety == 'group');
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
THROW NOT_IMPLEMENTED, "${ element.get_name } - complexType group not implemented yet";
ELSIF (complexType.get_variety == 'choice');
INCLUDE complexType/all.tt(complexType = complexType);
INCLUDE complexType/all.tt(complexType = complexType);
ELSIF (complexType.get_variety);
THROW NOT_IMPLEMENTED, "Unknown variety ${ complexType.get_variety } in ${ complexType.get_name } (${ element.get_name })";
THROW NOT_IMPLEMENTED, "Unknown variety ${ complexType.get_variety } in ${ complexType.get_name } (${ element.get_name })";
ELSE;
# There's no variety - might be empty complexType
# There's no variety - might be empty complexType
END;
%]

View File

@@ -14,26 +14,26 @@ __PACKAGE__->__set_ref([% IF element.get_ref; %]'[% element.get_ref %]'[% END %]
[%- IF (type = element.get_type); -%]
use base qw(
SOAP::WSDL::XSD::Typelib::Element
[% INCLUDE _type_class.tt( type = type, node = element ) %]
SOAP::WSDL::XSD::Typelib::Element
[% INCLUDE _type_class.tt( type = type, node = element ) %]
);
[%- ELSIF (ref = element.get_ref); -%]
# element ref="[% ref %]"
use base qw(
[% element_prefix %]::[% ref.split(':').1 %]
[% element_prefix %]::[% ref.split(':').1 %]
);
[%- ELSIF (simpleType = element.first_simpleType) %]
# atomic simpleType: <element><simpleType
# atomic simpleType: <element><simpleType
use base qw(
SOAP::WSDL::XSD::Typelib::Element
SOAP::WSDL::XSD::Typelib::Element
);
[% INCLUDE simpleType/contentModel.tt %]
[% ELSIF (complexType = element.first_complexType) %]
use base qw(
SOAP::WSDL::XSD::Typelib::Element
SOAP::WSDL::XSD::Typelib::ComplexType
SOAP::WSDL::XSD::Typelib::Element
SOAP::WSDL::XSD::Typelib::ComplexType
);
[% INCLUDE complexType/contentModel.tt;
[% INCLUDE complexType/contentModel.tt;
END %]

View File

@@ -1,30 +1,30 @@
[%- IF (name = element.get_type);
type_name = element.expand(name);
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
[%- IF (name = element.get_type);
type_name = element.expand(name);
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
$some_value, # [% type_name.1 %]
[%-
RETURN;
ELSIF (type = definitions.first_types.find_type( type_name ));
IF (type.isa('SOAP::WSDL::XSD::ComplexType') );
INCLUDE complexType/POD/structure.tt(complexType = type);
RETURN;
ELSE;
INCLUDE simpleType/POD/structure.tt(simpleType = type);
END;
RETURN;
END;
THROW NOT_FOUND, "no type found for {${type_name.0}}${type_name.1}";
[%-
RETURN;
ELSIF (type = definitions.first_types.find_type( type_name ));
IF (type.isa('SOAP::WSDL::XSD::ComplexType') );
INCLUDE complexType/POD/structure.tt(complexType = type);
RETURN;
ELSE;
INCLUDE simpleType/POD/structure.tt(simpleType = type);
END;
RETURN;
END;
THROW NOT_FOUND, "no type found for {${type_name.0}}${type_name.1}";
ELSIF (ref = element.get_ref);
ref_element = definitions.first_types.find_element( element.expand( ref ) );
INCLUDE element/POD/structure.tt(element = ref_element);
RETURN;
ref_element = definitions.first_types.find_element( element.expand( ref ) );
INCLUDE element/POD/structure.tt(element = ref_element);
RETURN;
ELSIF (type = element.first_simpleType);
INCLUDE simpleType/POD/structure.tt(simpleType = type);
RETURN;
INCLUDE simpleType/POD/structure.tt(simpleType = type);
RETURN;
ELSIF (type = element.first_complexType);
INCLUDE complexType/POD/structure.tt(complexType = type);
INCLUDE complexType/POD/structure.tt(complexType = type);
ELSE;
THROW NOT_FOUND, "no type found for ${element.get_name}";
THROW NOT_FOUND, "no type found for ${element.get_name}";
%]
NO TYPE FOUND FOR ELEMENT [% element.get_name %]
NO TYPE FOUND FOR ELEMENT [% element.get_name %]
[% END -%]

View File

@@ -5,8 +5,8 @@ use warnings;
sub get_xmlns { '[% simpleType.get_targetNamespace %]'};
[% INCLUDE simpleType/contentModel.tt %]
[%#
# Don't include any perl source here - there may be sub-packages...
[%#
# Don't include any perl source here - there may be sub-packages...
#-%]
1;
@@ -20,12 +20,12 @@ sub get_xmlns { '[% simpleType.get_targetNamespace %]'};
Perl data type class for the XML Schema defined simpleType
[% simpleType.get_name %] from the namespace [% simpleType.get_targetNamespace %].
[% IF (simpleType.get_variety == 'list');
INCLUDE simpleType/POD/list.tt;
ELSIF (simpleType.get_variety == 'restriction');
INCLUDE simpleType/POD/restriction.tt;
ELSE;
THROW NOT_IMPLEMENTED "simpleType union not implemented yet in $simpleType.get_name";
[% IF (simpleType.get_variety == 'list');
INCLUDE simpleType/POD/list.tt;
ELSIF (simpleType.get_variety == 'restriction');
INCLUDE simpleType/POD/restriction.tt;
ELSE;
THROW NOT_IMPLEMENTED "simpleType union not implemented yet in $simpleType.get_name";
END %]
=head1 METHODS

View File

@@ -1,20 +1,20 @@
This clase is derived from
[%-
[%-
IF (name = simpleType.get_itemType);
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END;
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END;
ELSE;
# THROW NOT_IMPLEMENTED "atomic simpleType list not implemented yet in $simpleType.get_name";
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
# THROW NOT_IMPLEMENTED "atomic simpleType list not implemented yet in $simpleType.get_name";
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
END -%].
You may pass the following structure to new():
[ $value_1, .. $value_n ]
All elements of the list must be of the class' base type (or
valid arguments to it's constructor).
All elements of the list must be of the class' base type (or valid arguments
to it's constructor).

View File

@@ -1,17 +1,16 @@
This clase is derived from
[%-
This clase is derived from [%-
IF (name = simpleType.get_base);
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END;
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% END;
ELSE;
# THROW NOT_IMPLEMENTED "atomic simpleType restriction not implemented yet in $simpleType.get_name";
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
# THROW NOT_IMPLEMENTED "atomic simpleType restriction not implemented yet in $simpleType.get_name";
%] a atomic base type. Unfortunately there's no documenatation generation for atomic base types yet. [%
END -%]
. SOAP::WSDL's schema implementation does not validate data, so you can use it exactly
. SOAP::WSDL's schema implementation does not validate data, so you can use it exactly
like it's base type.
# Description of restrictions not implemented yet.

View File

@@ -1,7 +1,7 @@
[% IF (simpleType.get_variety == 'list');
INCLUDE simpleType/list.tt(simpleType = simpleType);
[% IF (simpleType.get_variety == 'list');
INCLUDE simpleType/list.tt(simpleType = simpleType);
ELSIF (simpleType.get_variety == 'restriction');
INCLUDE simpleType/restriction.tt(type = simpleType);
ELSE;
THROW NOT_IMPLEMENTED "${ element.get_name } - ${ simpleType.get_variety } not supported yet";
INCLUDE simpleType/restriction.tt(type = simpleType);
ELSE;
THROW NOT_IMPLEMENTED "${ element.get_name } - ${ simpleType.get_variety } not supported yet";
END %]

View File

@@ -1,21 +1,21 @@
# list derivation
use base qw(
SOAP::WSDL::XSD::Typelib::Builtin::list
[%
SOAP::WSDL::XSD::Typelib::Builtin::list
[%
IF (name = simpleType.get_itemType);
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
type_name = simpleType.expand( name );
IF (type_name.0 == 'http://www.w3.org/2001/XMLSchema'); -%]
SOAP::WSDL::XSD::Typelib::Builtin::[% type_name.1 %]
);
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
[% ELSE -%]
[% type_prefix %]::[% type_name.1 %]
);
[% END;
[% END;
ELSIF (type = simpleType.first_simpleType); %]
);
[% INCLUDE simpleType/atomicType.tt(type = type);
[% INCLUDE simpleType/atomicType.tt(type = type);
ELSE; PERL %]die $stash->{simpleType}._DUMP [% END;
THROW UNKNOWN , "No list itemTape and no atomic simpleType - don't know what to do";
THROW UNKNOWN , "No list itemTape and no atomic simpleType - don't know what to do";
END %]

View File

@@ -1,9 +1,9 @@
# derivation by restriction
[% IF (base = simpleType.get_base) -%]
use base qw(
[% INCLUDE _type_class.tt(type = base, node=simpleType) %]);
[% INCLUDE _type_class.tt(type = base, node=simpleType) %]);
[% ELSIF (type = simpleType.first_simpleType() );
INCLUDE simpleType/atomicType.tt(type = type);
INCLUDE simpleType/atomicType.tt(type = type);
ELSE;
THROW "neither base nor atomic type - don't know what to do" %]
THROW "neither base nor atomic type - don't know what to do" %]
[% END %]

View File

@@ -11,9 +11,9 @@ my %element_prefix_of :ATTR(:name<element_prefix> :default<()>);
sub START {
my ($self, $ident, $arg_ref) = @_;
$type_prefix_of{ $ident } = 'MyType' if not exists
$type_prefix_of{ $ident } = 'MyType' if not exists
$arg_ref->{ 'type_prefix' };
$element_prefix_of{ $ident } = 'MyElement' if not exists
$element_prefix_of{ $ident } = 'MyElement' if not exists
$arg_ref->{ 'element_prefix' };
}
@@ -48,53 +48,53 @@ SOAP::WSDL::Generator::Visitor - SOAP::WSDL's Visitor-based Code Generator
=head1 DESCRIPTION
SOAP::WSDL featores a code generating facility. This code generation facility
(in fact there are several of them) is implemented as Visitor to
SOAP::WSDL featores a code generating facility. This code generation facility
(in fact there are several of them) is implemented as Visitor to
SOAP::WSDL::Base-derived objects.
=head2 The Visitor Pattern
The Visitor design pattern is one of the object oriented design pattern
The Visitor design pattern is one of the object oriented design pattern
described by [GHJV1995].
A Visitor is an object implementing some behaviour for a fixed set of classes,
whose implementation would otherwise need to be scattered accross those
A Visitor is an object implementing some behaviour for a fixed set of classes,
whose implementation would otherwise need to be scattered accross those
classes' implementations.
Visitors are usually combined with Iterators for traversing either a list or
Visitors are usually combined with Iterators for traversing either a list or
tree of objects.
A Visitor's methods are called using the so-called double dispatch technique.
To allow double dispatching, the Visitor implements one method for every class
ro be handled, whereas every class implements just one method (commonly named
"access"), which does nothing more than calling a method on the reference
A Visitor's methods are called using the so-called double dispatch technique.
To allow double dispatching, the Visitor implements one method for every class
ro be handled, whereas every class implements just one method (commonly named
"access"), which does nothing more than calling a method on the reference
given, with the self object as parameter.
If all this sounds strange, maybe an example helps. Imagine you had a list of
person objects and wanted to print out a list of their names (or address
stamps or everything elseyou like). This can easily be implemented with a
Visitor:
If all this sounds strange, maybe an example helps. Imagine you had a list of
person objects and wanted to print out a list of their names (or address
stamps or everything elseyou like). This can easily be implemented with a
Visitor:
package PersonVisitor;
use Class::Std; # handles all basic stuff like constructors etc.
sub visit_Person {
my ( $self, $object ) = @_;
print "Person name is ", $object->get_name(), "\n";
}
package Person;
use Class::Std;
my %name : ATTR(:name<name> :default<anonymous>);
sub accept { $_[1]->visit_Person( $_[0] ) }
package main;
my @person_from = ();
for (qw(Gamma Helm Johnson Vlissides)) {
push @person_from, Person->new( { name => $_ } );
}
my $visitor = PersonVisitor->new();
for (@person_from) {
$_->accept($visitor);
@@ -106,8 +106,8 @@ Visitor:
Person name is Johnson
Person name is Vlissides
While using this pattern for just printing a list may look a bit over-sized,
but it may become handy if you need multiple output formats and different
While using this pattern for just printing a list may look a bit over-sized,
but it may become handy if you need multiple output formats and different
classes to operate on.
The main benefits using visitors are:
@@ -116,19 +116,19 @@ The main benefits using visitors are:
=item * Grouping related behaviour in one class
Related behaviour for several classes can be grouped together in the Visitor
class. The behaviour can easily be changed by changing the code in one class,
Related behaviour for several classes can be grouped together in the Visitor
class. The behaviour can easily be changed by changing the code in one class,
instead of having to change all the visited classes.
=item * Cleaning up the data classes' implementations
If classes holding data also implement several different output formats or
If classes holding data also implement several different output formats or
other (otherwise unrelated) behaviour, they tend to get bloated.
=item * Adding behaviour is easy
=item * Adding behaviour is easy
Swapping out the visitor class allows easy alterations of behaviour. So on a
list of Persons, one Visitor may print address stamps, while another one prints
Swapping out the visitor class allows easy alterations of behaviour. So on a
list of Persons, one Visitor may print address stamps, while another one prints
out a phone number list.
=back
@@ -139,19 +139,19 @@ Of course, there are also drawbacks in the visitor pattern:
=item * Changes in the visited classes are expensive
If one of the visited classes changes (or is added), all visitors must be
updated to reflect this change. This may be rather expensive if classes change
If one of the visited classes changes (or is added), all visitors must be
updated to reflect this change. This may be rather expensive if classes change
often.
=item * The visited classes must expose all data required
Visitors may need to use the internals of a class. This may result in fidelling
Visitors may need to use the internals of a class. This may result in fidelling
with a object's internals, or a bloated interface in the visited class.
=back
Visitors are usually accompanied by a Iterator. The Iterator may be implemented
in the visited classes, in the Visitor, or somewhere else (in the example it
Visitors are usually accompanied by a Iterator. The Iterator may be implemented
in the visited classes, in the Visitor, or somewhere else (in the example it
was somewhere else).
The Iterator decides which object to visit next.
@@ -164,47 +164,47 @@ Code generation in SOAP::WSDL means generating various artefacts:
=item * Typemaps
For every WSDL definition, a Typemap is created. The Typemap is used later as
For every WSDL definition, a Typemap is created. The Typemap is used later as
an aid in parsing the SOAP XML messages.
=item * Type Classes
For every type defined in the WSDL's schema, a Type Class is generated.
For every type defined in the WSDL's schema, a Type Class is generated.
These classes are instantiated later as a result of parsing SOAP XML messages.
=item * Interface Classes
For every service, a interface class is generated. This class is later used by
For every service, a interface class is generated. This class is later used by
programmers accessing the service
=item * Documentation
Both Type Classes and Interface Classes include documentation. Additional
documentation may be generated as a hint for programmers, or later for
Both Type Classes and Interface Classes include documentation. Additional
documentation may be generated as a hint for programmers, or later for
mimicing .NET's .asmx example pages.
=back
All these behaviours could well (and has historically been) implemented in the
classes holding the WSDL data. This made these classes rather bloated, and
made it hard to change behaviour (like, supporting SOAP Headers,
supporting atomic types and other features which were missing from early
All these behaviours could well (and has historically been) implemented in the
classes holding the WSDL data. This made these classes rather bloated, and
made it hard to change behaviour (like, supporting SOAP Headers,
supporting atomic types and other features which were missing from early
versions of SOAP::WSDL).
Implementing these behaviours in Visitor classes eases adding new behaviours,
and reducing the incompletenesses still inherent in SOAP::WSDL's WSDL and XML
Implementing these behaviours in Visitor classes eases adding new behaviours,
and reducing the incompletenesses still inherent in SOAP::WSDL's WSDL and XML
schema implementation.
=head2 Implementation
=head3 accept
=head3 accept
SOAP::WSDL::Base defines an accept method which expects a Visitor as only
SOAP::WSDL::Base defines an accept method which expects a Visitor as only
parameter.
The method visit_Foo_Bar is called on the visitor, whith the self object as
parameter.
The method visit_Foo_Bar is called on the visitor, whith the self object as
parameter.
The actual method name is constructed this way:
@@ -218,18 +218,18 @@ The actual method name is constructed this way:
Example:
When visiting a SOAP::WSDL::XSD::ComplexType object, the method
When visiting a SOAP::WSDL::XSD::ComplexType object, the method
visit_XSD_ComplexType is called on the visitor.
=head2 Writing your own visitor
SOAP::WSDL eases writing your own visitor. This might be required if you need
some special output format from a WSDL file, or want to feed your own
serializer/deserializer pair with custom configuration data. Or maybe you want
SOAP::WSDL eases writing your own visitor. This might be required if you need
some special output format from a WSDL file, or want to feed your own
serializer/deserializer pair with custom configuration data. Or maybe you want
to generate C# code from it...
To write your own code generating visitor, you should subclass
SOAP::WSDL::Generator::Visitor. It implements (empty) default methods for all
To write your own code generating visitor, you should subclass
SOAP::WSDL::Generator::Visitor. It implements (empty) default methods for all
SOAP::WSDL data classes:
=over
@@ -264,16 +264,16 @@ SOAP::WSDL data classes:
=item * visit_XSD_SimpleType
=back
=back
In your Visitor, you must implement visit_Foo methods for all classes you wish
In your Visitor, you must implement visit_Foo methods for all classes you wish
to visit.
Currently, all SOAP::WSDL::Generator::Visitor implementations include their own
Iterator (which means they know how to find the next objects to visit). You
may or may not choose to implement a separate Iterator.
Currently, all SOAP::WSDL::Generator::Visitor implementations include their own
Iterator (which means they know how to find the next objects to visit). You
may or may not choose to implement a separate Iterator.
Letting a visitor implementing it's own Iterator visit a WSDL definition is as
Letting a visitor implementing it's own Iterator visit a WSDL definition is as
easy as writing something like this:
my $visitor = MyVisitor->new();
@@ -284,21 +284,21 @@ easy as writing something like this:
=head1 REFERENCES
=over
=over
=item * [GHJV1995]
=item * [GHJV1995]
Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides, (1995):
Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides, (1995):
Design Patterns. Elements of Reusable Object-Oriented Software.
Addison-Wesley Longman, Amsterdam.
=back
=back
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR

View File

@@ -18,32 +18,32 @@ sub START {
sub set_typemap_entry {
my ($self, $value) = @_;
$typemap_of{ ident $self }->{
join( q{/}, @{ $path_of{ ident $self } } )
} = $value;
$typemap_of{ ident $self }->{
join( q{/}, @{ $path_of{ ident $self } } )
} = $value;
}
sub add_element_path {
my ($self, $element) = @_;
# Swapping out this lines against the ones below generates
# Swapping out this lines against the ones below generates
# a namespace-sensitive typemap.
# Well almost: Class names are not constructed in a namespace-sensitive
# Well almost: Class names are not constructed in a namespace-sensitive
# manner, yet - there should be some facility to allow binding a (perl)
# prefix to a namespace...
push @{ $path_of{ ident $self } }, $element->get_name();
# push @{ $path_of{ ident $self } },
# "{". $element->get_targetNamespace . "}"
# push @{ $path_of{ ident $self } },
# "{". $element->get_targetNamespace . "}"
# . $element->get_name();
}
}
sub visit_Definitions {
my ( $self, $ident, $definitions ) = ( $_[0], ident $_[0], $_[1] );
$self->set_definitions( $definitions );
$self->set_definitions( $definitions );
for ( @{ $definitions->get_service() } ) {
for ( @{ $definitions->get_service() } ){
$_->_accept($self);
}
}
@@ -81,7 +81,7 @@ sub visit_Binding {
my $name = $operation->get_name();
# get the equally named operation from the portType
my ($op) = grep { $_->get_name eq $name }
my ($op) = grep { $_->get_name eq $name }
@{ $portType->get_operation() }
or die "operation <$name> not found";
@@ -122,14 +122,14 @@ sub visit_Part {
# FIXME support RPC-style calls
die "unsupported global type <$type_name> found in part";
}
# TODO factor out iterator or replace by lookup (probably better)
if ( my $element_name = $part->get_element() ) {
my $element = $types_ref->find_element(
my $element = $types_ref->find_element(
$part->expand($element_name) )
|| die "no element $element_name found for part " . $part->get_name();
$element->_accept($self);
return;
return;
}
warn 'neither type nor element - do not know what to do for part '
@@ -160,9 +160,9 @@ sub process_referenced_type {
}
sub process_atomic_type {
my ( $self, $type, $callback ) = @_;
my ( $self, $type, $callback ) = @_;
return if not $type;
my $ident = ident $self;
$callback->( $self, $type ) if $callback;
return $self;
@@ -171,40 +171,40 @@ sub process_atomic_type {
sub visit_XSD_Element {
my ( $self, $ident, $element ) = ( $_[0], ident $_[0], $_[1] );
# TODO: what about element ref="" ?
# TODO: what about element ref="" ?
# when we're hopping from one element to the next one...
# step down in tree
$self->add_element_path( $element );
# now call all possible variants.
# They all just return if no argument is given,
# They all just return if no argument is given,
# and return $self on success.
SWITCH: {
if ($element->get_type) {
$self->process_referenced_type( $element->expand( $element->get_type() ) )
if ($element->get_type) {
$self->process_referenced_type( $element->expand( $element->get_type() ) )
&& last;
}
# for atomic simple and comples types , and ref elements
my $typeclass = join q{::}, $element_prefix_of{$ident}, $element->get_name();
$self->set_typemap_entry($typeclass);
# kind of double-dispatch: returns true on success, but does nothing
$self->process_atomic_type( $element->first_simpleType() )
&& last;
$self->process_atomic_type( $element->first_complexType()
, sub { $_[1]->_accept($_[0]) } )
&& last;
# TODO: add element ref handling
# TODO: add element ref handling
};
# step up in hierarchy
pop @{ $path_of{$ident} };
}
sub visit_XSD_ComplexType {
sub visit_XSD_ComplexType {
my ($self, $ident, $type) = ($_[0], ident $_[0], $_[1] );
my $content_model = $type->get_flavor();
# TODO is this allowed ? or should we better die ?
@@ -218,9 +218,9 @@ sub visit_XSD_ComplexType {
}
return;
}
warn "unsupported content model $content_model found in "
. "complex type " . $type->get_name()
. "complex type " . $type->get_name()
. " - typemap may be incomplete";
}

View File

@@ -12,12 +12,12 @@ SOAP::WSDL::Manual - Accessing WSDL based web services
=item * Create WSDL bindings
perl wsdl2perl.pl -b base_dir URL
perl wsdl2perl.pl -b base_dir URL
=item * Look what has been generated
Check the results of the generator. There should be one
MyInterfaces/SERVICE_NAME/PORT_NAME.pm file per port (and one directory per
Check the results of the generator. There should be one
MyInterfaces/SERVICE_NAME/PORT_NAME.pm file per port (and one directory per
service).
=item * Write script
@@ -30,14 +30,14 @@ service).
print $result;
C<perldoc MyInterface::SERVICE_NAME::PORT_NAME> should give you some overview
C<perldoc MyInterface::SERVICE_NAME::PORT_NAME> should give you some overview
about the service's interface structure.
The results of all calls to your service object's methods (except new) are
The results of all calls to your service object's methods (except new) are
objects based on SOAP::WSDL's XML schema implementation.
To access the object's properties use get_NAME / set_NAME getter/setter
methods whith NAME corresponding to the XML tag name / the hash structure as
To access the object's properties use get_NAME / set_NAME getter/setter
methods whith NAME corresponding to the XML tag name / the hash structure as
showed in the generated pod.
=item * Run script
@@ -46,61 +46,61 @@ showed in the generated pod.
=head2 Instrumenting web services with interface classes
SOAP::WSDL (starting from 2.00) instruments WSDL based web services with
interface classes. This means that SOAP::WSDL features a code generator
SOAP::WSDL (starting from 2.00) instruments WSDL based web services with
interface classes. This means that SOAP::WSDL features a code generator
which creates one class for every web service you want to access.
Moreover, the data types from the WSDL definitions are also wrapped into
classes and returned to the user as objects.
Moreover, the data types from the WSDL definitions are also wrapped into
classes and returned to the user as objects.
To find out which class a particular XML node should be, SOAP::WSDL uses
To find out which class a particular XML node should be, SOAP::WSDL uses
typemaps. For every Web service, there's also a typemap created.
=head2 Interface class creation
To create interface classes, follow the steps above from
To create interface classes, follow the steps above from
L<Quick walk-through for the unpatient|Quick walk-through for the unpatient>.
If this works fine for you, skip the next paragraphs. If not, read on.
The steps to instrument a web service with SOAP::WSDL perl bindings
The steps to instrument a web service with SOAP::WSDL perl bindings
(in detail) are as follows:
=over
=item * Gather web service information
You'll need to know at least a URL pointing to the web service's WSDL
You'll need to know at least a URL pointing to the web service's WSDL
definition.
If you already know more - like which methods the service provides, or how
the XML messages look like, that's fine. All these things will help you
If you already know more - like which methods the service provides, or how
the XML messages look like, that's fine. All these things will help you
later.
=item * Create WSDL bindings
perl wsdl2perl.pl -b base_dir URL
perl wsdl2perl.pl -b base_dir URL
This will generate the perl bindings in the directory specified by base_dir.
For more options, see L<wsdl2perl.pl> - you may want to specify class
prefixes for XML type and element classes, type maps and interface classes,
For more options, see L<wsdl2perl.pl> - you may want to specify class
prefixes for XML type and element classes, type maps and interface classes,
and you may even want to add custom typemap elements.
=item * Check the result
There should be a bunch of classes for types (in the MyTypes:: namespace by
default), elements (in MyElements::), and at least one typemap (in
There should be a bunch of classes for types (in the MyTypes:: namespace by
default), elements (in MyElements::), and at least one typemap (in
MyTypemaps::) and one ore more interface classes (in MyInterfaces::).
If you don't already know the details of the web service you're going to
instrument, it's now time to read the perldoc of the generated interface
classes. It will tell you what methods each service provides, and which
If you don't already know the details of the web service you're going to
instrument, it's now time to read the perldoc of the generated interface
classes. It will tell you what methods each service provides, and which
parameters they take.
If the WSDL definition is informative about what these methods do, the
If the WSDL definition is informative about what these methods do, the
included perldoc will be, too - if not, blame the web service author.
=item * Write a perl script (or module) accessing the web service.
use MyInterface::SERVICE_NAME;
@@ -110,24 +110,24 @@ included perldoc will be, too - if not, blame the web service author.
die $result if not $result;
print $result;
The above handling of errors ("die $result if not $result") may look a bit
strange - it is due to the nature of
L<SOAP::WSDL::SOAP::Typelib::Fault11|SOAP::WSDL::SOAP::Typelib::Fault11>
The above handling of errors ("die $result if not $result") may look a bit
strange - it is due to the nature of
L<SOAP::WSDL::SOAP::Typelib::Fault11|SOAP::WSDL::SOAP::Typelib::Fault11>
objects SOAP::WSDL uses for signalling failure.
These objects are false in boolean context, but serialize to their XML
These objects are false in boolean context, but serialize to their XML
structure on stringification.
You may, of course, access individual fault properties, too. To get a list of
You may, of course, access individual fault properties, too. To get a list of
fault properties, see L<SOAP::WSDL::SOAP::Typelib::Fault11>
=back
=head2 Adding missing information
Sometimes, WSDL definitions are incomplete. In most of these cases, proper
fault definitions are missing. This means that though the specification sais
nothing about it, Fault messages include extra elements in the
Sometimes, WSDL definitions are incomplete. In most of these cases, proper
fault definitions are missing. This means that though the specification says
nothing about it, Fault messages include extra elements in the
E<lt>detailE<gt> section, or errors are even indicated by non-fault messages.
There are two steps you need to perform for adding additional information.
@@ -136,38 +136,38 @@ There are two steps you need to perform for adding additional information.
=item * Provide required type classes
For each extra data type used in the XML messages, a type class has to be
created.
For each extra data type used in the XML messages, a type class has to be
created.
It is strongly discouraged to use the same namespace for hand-written and
generated classes - while generated classes may be many, you probably will
only implement a few by hand. These (precious) few classes may get lost in
the mass of (cheap) generated ones. Just imagine one of your co-workers (or
even yourself) deleting the whole bunch and re-generating everything - oops
It is strongly discouraged to use the same namespace for hand-written and
generated classes - while generated classes may be many, you probably will
only implement a few by hand. These (precious) few classes may get lost in
the mass of (cheap) generated ones. Just imagine one of your co-workers (or
even yourself) deleting the whole bunch and re-generating everything - oops
- almost everything. You got the point.
For simplicity, you probably just want to use builtin types wherever possible
- you are probably not interested in whether a fault detail's error code is
presented to you as a simpleType ranging from 1 to 10 (which you have to
write) or as a int (which is a builtin type ready to use).
For simplicity, you probably just want to use builtin types wherever possible
- you are probably not interested in whether a fault detail's error code is
presented to you as a simpleType ranging from 1 to 10 (which you have to
write) or as a int (which is a builtin type ready to use).
Using builtin types for simpleType definitions may greatly reduce the number
Using builtin types for simpleType definitions may greatly reduce the number
of additional classes you need to implement.
If the extra type classes you need include E<lt>complexType E<gt> or
E<lt>element /E<gt> definitions, see L<SOAP::WSDL::SOAP::Typelib::ComplexType>
and L<SOAP::WSDL::SOAP::Typelib::Element> on how to create ComplexType and
If the extra type classes you need include E<lt>complexType E<gt> or
E<lt>element /E<gt> definitions, see L<SOAP::WSDL::SOAP::Typelib::ComplexType>
and L<SOAP::WSDL::SOAP::Typelib::Element> on how to create ComplexType and
Element type classes.
=item * Provide a typemap snippet to wsdl2perl.pl
SOAP::WSDL uses typemaps for finding out into which class' object a XML node
SOAP::WSDL uses typemaps for finding out into which class' object a XML node
should be transformed.
Typemaps basically map the path of every XML element inside the Body tag to a
Typemaps basically map the path of every XML element inside the Body tag to a
perl class.
Typemap snippets have to look like this (which is actually the default Fault
Typemap snippets have to look like this (which is actually the default Fault
typemap included in every generated one):
(
@@ -178,11 +178,11 @@ typemap included in every generated one):
'Fault/detail' => 'SOAP::WSDL::XSD::Typelib::Builtin::anyType',
);
The lines are hash key - value pairs. The keys are the XPath expressions
without occurence numbers (like [1]) relative to the Body element.
Namespaces are ignored.
The lines are hash key - value pairs. The keys are the XPath expressions
without occurence numbers (like [1]) relative to the Body element.
Namespaces are ignored.
If you don't know about XPath: They are just the names of the XML tags,
If you don't know about XPath: They are just the names of the XML tags,
starting from the one inside E<lt>BodyE<gt> up to the current one joined by /.
One line for every XML node is required.
@@ -191,46 +191,45 @@ You may use all builtin, generated or custom type class names as values.
Use wsdl2perl.pl -mi=FILE to include custom typemap snippets.
Note that typemap include files for wsdl2perl.pl must evaluate to a valid
perl hash - it will be imported via eval (OK, to be honest: via I<do $file>,
Note that typemap include files for wsdl2perl.pl must evaluate to a valid
perl hash - it will be imported via eval (OK, to be honest: via I<do $file>,
but that's almost the same...).
Your extra statements are included last, so they override potential typemap
Your extra statements are included last, so they override potential typemap
statements with the same keys.
=back
=head1 Accessing a web service without a WSDL definition
Accessing a web service without a WSDL definition is more cumbersome. There
are two ways to go:
Accessing a web service without a WSDL definition is more cumbersome. There
are two ways to go:
=over
=item * Write a WSDL definition and generate interface
This is the way to go if you already are experienced in writing WSDL files.
If you are not, be warned: Writing a correct WSDL is not an easy task, and
writing correct WSDL files with only a text editor is almost impossible.
You should definitely use a WSDL editor. The WSDL editor should support
conformance checks for the WS-I Basic Profile (1.0 is preferred by
SOAP::WSDL)
=item * Write a typemap and class library from scratch
If the web service is relatively simple, this is probably easier than first
writing a WSDL definition. Besides, it can be done in perl, a language you
are probably more familiar with than WSDL.
L<SOAP::WSDL::XSD::Typelib::ComplexType>, L<SOAP::WSDL::XSD::Typelib::SimpleType> and
L<SOAP::WSDL::XSD::Typelib::Element> tell you how to create subclasses of XML schema
types.
L<SOAP::WSDL::Manual::Parser> will tell you how to create a typemap class.
=item * Write a WSDL definition and generate interface
This is the way to go if you already are experienced in writing WSDL files.
If you are not, be warned: Writing a correct WSDL is not an easy task, and
writing correct WSDL files with only a text editor is almost impossible.
You should definitely use a WSDL editor. The WSDL editor should support
conformance checks for the WS-I Basic Profile (1.0 is preferred by
SOAP::WSDL)
=item * Write a typemap and class library from scratch
If the web service is relatively simple, this is probably easier than first
writing a WSDL definition. Besides, it can be done in perl, a language you
are probably more familiar with than WSDL.
L<SOAP::WSDL::XSD::Typelib::ComplexType>, L<SOAP::WSDL::XSD::Typelib::SimpleType> and
L<SOAP::WSDL::XSD::Typelib::Element> tell you how to create subclasses of XML schema
types.
L<SOAP::WSDL::Manual::Parser> will tell you how to create a typemap class.
=back
=head1 Troubleshooting
=head2 Accessing HTTPS webservices
@@ -239,40 +238,40 @@ You need Crypt::SSLeay installed to access HTTPS webservices.
=head2 Accessing protected web services
Passing a userndame and password, or a client certificate and key, to the
Passing a userndame and password, or a client certificate and key, to the
transport layer is highly dependent on the transport backend.
=head3 Accessing HTTP(S) webservices with basic/digest authentication
When using SOAP::WSDL::Transport::HTTP (SOAP::Lite not installed), add a
When using SOAP::WSDL::Transport::HTTP (SOAP::Lite not installed), add a
method called "get_basic_credentials" to SOAP::WSDL::Transport::HTTP:
*SOAP::WSDL::Transport::HTTP::get_basic_credentials = sub {
return ($user, $password);
return ($user, $password);
};
When using SOAP::Transport::HTTP (SOAP::Lite is installed), do the same to
When using SOAP::Transport::HTTP (SOAP::Lite is installed), do the same to
this backend:
*SOAP::Transport::HTTP::get_basic_credentials = sub {
return ($user, $password);
return ($user, $password);
};
=head3 Accessing HTTP(S) webservices protected by NTLM authentication
Besides passing user credentials as when accessing a web service protected
by basic or digest authentication, you also need to enforce connection
Besides passing user credentials as when accessing a web service protected
by basic or digest authentication, you also need to enforce connection
keep_alive on the transport backens.
To do so, pass a I<proxy> argument to the new() method of the generated
To do so, pass a I<proxy> argument to the new() method of the generated
class. This unfortunately means that you have to set the endpoint URL, too:
my $interface = MyInterfaces::SERVICE_NAME::PORT_NAME->new({
proxy => [ $url, keep_alive => 1 ]
});
You may, of course, decide to just hack the generated class. Be advised that
subclassing might be a more appropriate solution - re-generating overwrites
You may, of course, decide to just hack the generated class. Be advised that
subclassing might be a more appropriate solution - re-generating overwrites
changes in interface classes.
=head3 Accessing HTTPS webservices protected by certificate authentication
@@ -283,17 +282,19 @@ See L<Crypt::SSLeay> on how to configure client certificate authentication.
=head1 SEE ALSO
L<SOAP::WSDL::Manual::XSD> SOAP::WSDL's XML Schema implementation
L<SOAP::WSDL::Manual::Glossary> The meaning of all these words
L<SOAP::WSDL::Client> Basic client for SOAP::WSDL based interfaces
L<SOAP::WSDL> an interpreting WSDL based SOAP client
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR

View File

@@ -0,0 +1,49 @@
=pod
=head1 NAME
SOAP::WSDL::Manual::Deserializer
=head1 DESERIALIZER CLASSES
Deserializer classes convert SOAP messages to perl data structures.
SOAP::WSDL comes with several builtin serializer classes:
=over
=item * L<SOAP::WSDL::Deserializer::XSD|SOAP::WSDL::Deserializer::XSD>
Creates SOAP::WSDL::XSD objects from SOAP messages. Default deserializer for
generated interfaces and SOAP::WSDL::Client.
=item * L<SOAP::WSDL::Deserializer::Hash|SOAP::WSDL::Deserializer::Hash>
Creates perl hash structures from SOAP messages.
=item * L<SOAP::WSDL::Deserializer::SOM|SOAP::WSDL::Deserializer::SOM>
Creates SOAP::SOM objects from SOAP messages. Default deserializer for
SOAP::WSDL.
See L<SOAP::Lite> for more information on SOAP::SOM objects.
=back
=head1 WRITING YOUR OWN DESERIALIZER
See L<SOAP::WSDL::Factory::Deserializer>.
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under the same
terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=cut

View File

@@ -6,55 +6,56 @@ SOAP::WSDL::Manual::Glossary - Those acronyms and stuff
=head2 web service
Web services are RPC (Remote Procedure Call) interfaces accessible via
some internet protocol, typically via HTTP(S).
Web services are RPC (Remote Procedure Call) interfaces accessible via
some internet protocol, typically via HTTP(S).
=head2 SOAP
SOAP is an acronym for Simple Object Access Protocol.
SOAP is a W3C recommendation. The latest version of the SOAP
specification may be found at L<http://www.w3.org/TR/soap/>.
SOAP is (was - since 1.2 the name "SOAP" has no meaning any more) an acronym
for Simple Object Access Protocol.
SOAP is a W3C recommendation. The latest version of the SOAP specification
may be found at L<http://www.w3.org/TR/soap/>.
SOAP defines a protocoll for message exchange between applications.
SOAP defines a protocoll for message exchange between applications.
The most popular usage is to use SOAP for remote procedure calls (RPC).
While one of the constituting aspects of a web service is its
reachability via some internet protocol, you might as well define
While one of the constituting aspects of a web service is its
reachability via some internet protocol, you might as well define
SOAP services accessible via postcards.
Despite it's name, SOAP has nothing more to do with objects than
cars have with pets - SOAP messages may, but not neccessarily do
carry objects, very much like your car may, but does not need to
Despite it's former name, SOAP has nothing more to do with objects than
cars have with pets - SOAP messages may, but not necessarily do
carry objects, very much like your car may, but does not need to
carry your pet.
=head2 WSDL
WSDL is an acronym for Web Services Description Language.
WSDL is a W3C recommendation. The latest version of the WSDL specification
may be found at L<http://www.w3.org/TR/wsdl20/>.
WSDL is an acronym for Web Services Description Language.
WSDL is a W3C recommendation. The latest version of the WSDL specification
may be found at L<http://www.w3.org/TR/wsdl20/>.
WSDL defines a XML-based language for describing web service interfaces,
WSDL defines a XML-based language for describing web service interfaces,
including SOAP interfaces.
=head2 WS-I
WS-I (Web Services Interoperability Organization) is an open industry
organisation chartered to promote Web service interoperability across
WS-I (Web Services Interoperability Organization) is an open industry
organisation chartered to promote Web service interoperability across
platforms, operating systems, and programming languages.
WS-I publishes profiles, which provide implementation guidelines for
how related Web services specifications should be used together for
best interoperability. To date, WS-I has finalized the Basic Profile,
Attachments Profile and Simple SOAP Binding Profile.
WS-I publishes profiles, which provide implementation guidelines for
how related Web services specifications should be used together for
best interoperability. To date, WS-I has finalized the Basic Profile,
Attachments Profile and Simple SOAP Binding Profile.
SOAP::WSDL aims at complying to the Basic Profile (but does not
SOAP::WSDL aims at complying to the WS-I Basic Profile (but does not
implement full support yet).
=head2 SOAP message styles
=head3 rpc
Meant for transporting a RPC message. All contents of the SOAP body are
Meant for transporting a RPC message. All contents of the SOAP body are
put into a top-level node named equal to the SOAP operation.
WS-I Basic Profile allows the use of rpc message style.
@@ -65,7 +66,7 @@ SOAP::Lite supports rpc message style only.
=head3 document
Meant for transporting arbitrary content. No additional nodes are inserted
Meant for transporting arbitrary content. No additional nodes are inserted
between the SOAP body and the actual content.
WS-I Basic Profile allows the use of document message style.
@@ -76,16 +77,23 @@ WS-I Basic Profile allows the use of document message style.
=head3 literal
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
This file is part of SOAP-WSDL. You may distribute/modify it under the same
terms as perl itself.
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Glossary.pod 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Manual/Glossary.pod $
=cut

View File

@@ -6,7 +6,7 @@ SOAP::WSDL::Manual::Parser - How SOAP::WSDL parses XML messages
=head1 Which XML message does SOAP::WSDL parse ?
Naturally, there are two kinds of XML documents (or messages) SOAP::WSDL has
Naturally, there are two kinds of XML documents (or messages) SOAP::WSDL has
to parse:
=over
@@ -17,77 +17,38 @@ to parse:
=back
=head1 Parser implementations
There are different parser implementations available for SOAP messages and
There are different parser implementations available for SOAP messages and
WSDL definitions.
Historically, SOAP::WSDL used SAX for parsing XML. The SAX handlers were
implemented as L<XML::LibXML|XML::LibXML> handlers, which also worked with
L<XML::SAX::ParserFactory|XML::SAX::ParserFactory>.
=head1 WSDL definitions parser
Support for SAX and L<XML::LibXML|XML::LibXML> in SOAP::WSDL is discontinued
for the following reasons:
=over
=item * Speed
L<XML::Parser::Expat|XML::Parser::Expat> is faster than
L<XML::LibXML|XML::LibXML> - at least when optimized for speed.
High parsing speed is one of the key requirements for a SOAP toolkit - if XML
serializing and (more important) deserializing are not fast enough, the whole
toolkit is unusable.
=item * Availability
L<XML::Parser|XML::Parser> is more popular than L<XML::LibXML|XML::LibXML>.
=item * Stability
XML::LibXML is based on the libxml2 library. Several versions of
libxml2 are known to have specific bugs. As a workaround, there are
often several versions of libxml2 installed on one system. This may
lead to problems on operating systems which cannot load more than
one version of a shared library simultaneously.
XML::LibXML is also still under development, while XML::Parser has had time
to stabilize.
=item * SOAP::Lite uses XML::Parser
L<SOAP::Lite|SOAP::Lite> uses L<XML::Parser|XML::Parser> if available.
SOAP::WSDL should not require users to install both L<XML::Parser|XML::Parser>
and L<XML::LibXML|XML::LibXML>.
=back
=head2 WSDL definitions parser
=over
=item * SOAP::WSDL::Expat::WSDLParser
=head2 SOAP::WSDL::Expat::WSDLParser
A parser for WSDL definitions based on L<XML::Parser::Expat|XML::Parser::Expat>.
my $parser = SOAP::WSDL::Expat::WSDLParser->new();
my $wsdl = $parser->parse_file( $filename );
=back
The WSDL parser creates a tree of perl objects, whose root is a
L<SOAP::WSDL::Definitions|SOAP::WSDL::Definitions> element.
=head2 SOAP messages parser
=head1 SOAP messages parser
All SOAP message handler use class resolvers for finding out which class
=head2 SOAP::WSDL::Expat::MessageParser
L<SOAP::WSDL::Expat::MessageParser|SOAP::WSDL::Expat::MessageParser> converts
SOAP messages to SOAP::WSDL::XSD object trees.
It uses a class resolvers for finding out which class
a particular XML element should be of, and type libs containing these classes.
=head3 Creating a class resolver
The easiest way for creating a class resolver is to run SOAP::WSDL's generator.
See wsdl2perl.pl
See L<wsdl2perl.pl>.
The class resolver must implement a class method "get_class", which is passed
The class resolver must implement a class method "get_class", which is passed
a list ref of the current element's XPath (relative to Body), split by /.
This method must return a class name appropriate for a XML element.
@@ -116,10 +77,10 @@ A class resolver package might look like this:
Sometimes there's unneccessary information transported in SOAP messages.
To skip XML nodes (including all child nodes), just edit the type map for
the message and set the type map entry to '__SKIP__'.
To skip XML nodes (including all child nodes), just edit the type map for
the message and set the type map entry to '__SKIP__'.
In the example above, EnqueueMessage/StuffIDontNeed and all child elements
In the example above, EnqueueMessage/StuffIDontNeed and all child elements
are skipped.
my %class_list = (
@@ -132,7 +93,7 @@ are skipped.
'EnqueueMessage/StuffIDontNeed/Bar' => 'SOAP::WSDL::XSD::Builtin::string',
);
Note that only SOAP::WSDL::Expat::MessageParser implements skipping elements
Note that only SOAP::WSDL::Expat::MessageParser implements skipping elements
at the time of writing.
=head3 Creating type lib classes
@@ -141,81 +102,87 @@ Every element must have a correspondent one in the type library.
Builtin types should be resolved as SOAP::WSDL::XSD::Builtin::* classes
Creating a type lib is easy: Just run SOAP::WSDL's generator - it will
Creating a type lib is easy: Just run SOAP::WSDL's generator - it will
create both a typemap and the type lib classes for a WSDL file.
Sometimes it is nessecary to create type lib classes by hand - not all
Sometimes it is nessecary to create type lib classes by hand - not all
WSDL definitions are complete.
For writing your own lib classes, see L<SOAP::WSDL::XSD::Typelib::Element>,
L<SOAP::WSDL::XSD::Typelib::ComplexType> and L<SOAP::WSDL::XSD::Typelib::SimpleType>.
=head3 Parser implementations
=head2 SOAP::WSDL::Expat::Message2Hash
Transforms a SOAP message into a perl hash refs. Using this parser is usually
triggered by calling the C<outputhash> method of SOAP::WSDL, or by using
L<SOAP::WSDL::Deserializer::Hash|SOAP::WSDL::Deserializer::Hash>.
Acts somewhat like XML::Simple, but faster.
The following restrictions apply:
=over
=item * SOAP::WSDL::Expat::MessageParser
=item * Ignores all namespaces
A L<XML::Parser::Expat|XML::Parser::Expat> based parser. This is the fastest
parser for most SOAP messages and the default for SOAP::WSDL::Client.
=item * Ignores all attributes
=item * SOAP::WSDL::Expat::MessageStreamParser
=item * Does not handle mixed content
A XML::Parser::ExpatNB based parser. Useful for parsing huge HTTP responses,
as you don't need to keep everything in memory.
See L<SOAP::WSDL::Expat::MessageStreamParser|SOAP::WSDL::Expat::MessageStreamParser>
for details.
=item * The SOAP header is ignored
=back
=head3 Performance
SOAP::WSDL::Expat::MessageParser is the fastest way of parsing SOAP messages
into object trees and only slightly slower than converting them into hash
data structures:
Parsing a SOAP message with a length of 5962 bytes:
SOAP::WSDL::Expat::MessageParser:
3 wallclock secs ( 3.28 usr + 0.05 sys = 3.33 CPU) @ 60.08/s (n=200)
SOAP::WSDL::SAX::MessageHandler (with raw XML::LibXML):
5 wallclock secs ( 4.95 usr + 0.00 sys = 4.95 CPU) @ 40.38/s (n=200)
XML::Simple (XML::Parser):
3 wallclock secs ( 2.36 usr + 0.03 sys = 2.39 CPU) @ 83.65/s (n=200)
XML::Simple (XML::SAX::Expat):
7 wallclock secs ( 6.50 usr + 0.03 sys = 6.53 CPU) @ 30.62/s (n=200)
As the benchmark shows, all SOAP::WSDL parser variants are faster than
XML::Simple with XML::SAX::Expat, and SOAP::WSDL::Expat::MessageParser almost
reaches the performance of XML::Simple with XML::Parser as backend.
Parsing SOAP responses in chunks does not increase speed - at least not up
to a response size of around 500k:
Benchmark: timing 5 iterations of SOAP::WSDL::SAX::MessageHandler,
SOAP::WSDL::Expat::MessageParser, SOAP::WSDL::Expat::MessageStreamParser...
SOAP::WSDL::Expat::MessageStreamParser:
13 wallclock secs ( 7.39 usr + 0.09 sys = 7.48 CPU) @ 0.67/s (n=5)
SOAP::WSDL::Expat::MessageParser:
10 wallclock secs ( 5.81 usr + 0.06 sys = 5.88 CPU) @ 0.85/s (n=5)
SOAP::WSDL::SAX::MessageHandler:
14 wallclock secs ( 8.78 usr + 0.03 sys = 8.81 CPU) @ 0.57/s (n=5)
Response size: 344330 bytes
=cut
=head1 OLD SAX HANDLER
The old SAX handler historically used in SOAP::WSDL are not included in
Historically, SOAP::WSDL used SAX for parsing XML. The SAX handlers were
implemented as L<XML::LibXML|XML::LibXML> handlers, which also worked with
L<XML::SAX::ParserFactory|XML::SAX::ParserFactory>.
Support for SAX and L<XML::LibXML|XML::LibXML> in SOAP::WSDL is discontinued
for the following reasons:
=over
=item * Speed
L<XML::Parser::Expat|XML::Parser::Expat> is faster than
L<XML::LibXML|XML::LibXML> - at least when optimized for speed.
High parsing speed is one of the key requirements for a SOAP toolkit - if XML
serializing and (more important) deserializing are not fast enough, the whole
toolkit is unusable.
=item * Availability
L<XML::Parser|XML::Parser> is more popular than L<XML::LibXML|XML::LibXML>.
=item * Stability
XML::LibXML is based on the libxml2 library. Several versions of
libxml2 are known to have specific bugs. As a workaround, there are
often several versions of libxml2 installed on one system. This may
lead to problems on operating systems which cannot load more than
one version of a shared library simultaneously.
XML::LibXML is also still under development, while XML::Parser has had time
to stabilize.
=item * SOAP::Lite uses XML::Parser
L<SOAP::Lite|SOAP::Lite> uses L<XML::Parser|XML::Parser> if available.
SOAP::WSDL should not require users to install both L<XML::Parser|XML::Parser>
and L<XML::LibXML|XML::LibXML>.
=back
The old SAX handler historically used in SOAP::WSDL are not included in
the SOAP::WSDL package any more.
However, they may be obtained from the "attic" directory in
SOAP::WSDL's SVN repository at
However, they may be obtained from the "attic" directory in
SOAP::WSDL's SVN repository at
https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/attic
@@ -223,10 +190,10 @@ https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/attic
=item * SOAP::WSDL::SAX::WSDLHandler
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
works with.
It's built as a native handler for XML::LibXML, but will also work with
It's built as a native handler for XML::LibXML, but will also work with
XML::SAX::ParserFactory.
To parse a WSDL file, use one of the following variants:
@@ -237,7 +204,6 @@ To parse a WSDL file, use one of the following variants:
$parser->parse( $xml );
my $data = $handler->get_data();
my $handler = SOAP::WSDL::SAX::WSDLHandler->new({
base => 'XML::SAX::Base'
});
@@ -247,18 +213,35 @@ To parse a WSDL file, use one of the following variants:
$parser->parse( $xml );
my $data = $handler->get_data();
=item * SOAP::WSDL::SAX::MessageHandler
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
This is a SAX handler for parsing WSDL files into object trees SOAP::WSDL
works with.
It's built as a native handler for XML::LibXML, but will also work with
It's built as a native handler for XML::LibXML, but will also work with
XML::SAX::ParserFactory.
Can be used for parsing both streams (chunks) and documents.
Can be used for parsing both streams (chunks) and documents.
=back
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself.
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Parser.pod 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Manual/Parser.pod $
=cut
=cut

View File

@@ -0,0 +1,30 @@
=pod
=head1 NAME
SOAP::WSDL::Manual::Serializer
=head1 SERIALIZER CLASSES
Serializer classes convert perl data structures to XML.
SOAP::WSDL comes with one builtin serializer class:
L<SOAP::WSDL::Serializer::XSD|SOAP::WSDL::Serializer::XSD>.
=head1 WRITING YOUR OWN SERIALIZER
See L<SOAP::WSDL::Factory::Serializer>.
=head1 LICENSE
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=cut

File diff suppressed because it is too large Load Diff

View File

@@ -6,76 +6,102 @@ SOAP::WSDL::Manual::XSD - SOAP::WSDL's XML Schema implementation
=head1 DESCRIPTION
SOAP::WSDL's XML Schema implementation translates XML Schema definitions into
SOAP::WSDL's XML Schema implementation translates XML Schema definitions into
perl classes.
Every top-level type or element in a XML schema is translated into a perl
Every top-level type or element in a XML schema is translated into a perl
class (usually in it's own file).
Atomic types are either directly included in the class of their parent's
Atomic types are either directly included in the class of their parent's
node, or as sub-package in their parent class' file.
While the implementation is still incomplete, it covers the XML schema
While the implementation is still incomplete, it covers the XML schema
definitions used by most object mappers.
=head1 USAGE
You can use SOAP::WSDL::XSD based classes just like any perl class - you may
You can use SOAP::WSDL::XSD based classes just like any perl class - you may
instantiate it, inherit from it etc.
You should be aware, that SOAP::WSDL::XSD based classes are inside-out
classes using Class::Std, though - things you would expect from hash-based
You should be aware, that SOAP::WSDL::XSD based classes are inside-out
classes using Class::Std, though - things you would expect from hash-based
classes like using the blessed hash ref as data storage won't work.
Moreover, most classes override Class::Std's default constructor for speed -
you should not expect BUILD or START methods to work, unless you call them
yourself (or define a new constructor).
Moreover, most all SOAP::WSDL::XSD::Typelib based classes override
Class::Std's default constructor for speed - you should not expect BUILD or
START methods to work, unless you call them yourself (or define a new
constructor).
All SOAP::WSDL::XSD based complexType classes allow a hash ref mathing their
data structure as only parameter to new(). You may mix hash and list refs and
objects in the structure passed to new - as long as the structure matches, it
All SOAP::WSDL::XSD based complexType classes allow a hash ref matching their
data structure as only parameter to new(). You may mix hash and list refs and
objects in the structure passed to new - as long as the structure matches, it
will work fine.
All SOAP::WSDL::XSD based simpleType (and builtin) classes accept a single
All SOAP::WSDL::XSD based simpleType (and builtin) classes accept a single
hash ref with the only key "value" and the value to be set as value.
All SOAP::WSDL::XSD based classes overload arrayification - that is being
accessed as a list ref - with a method returning [ $self ].
This means that you can safely use the results of get_ELEMENT calls on
cmplexTypes as list refs (you'll have to check for definedness, though -
see L<SOAP::WSDL::XSD::Typelib::Builtin|SOAP::WSDL::XSD::Typelib::Builtin>
for details.
To iterate over a (potential) list of child elements just do the following:
if (defined $obj->get_ELEMENT()) {
for (@{ $obj->get_ELEMENT() }) {
...
}
}
This is especially useful in mini-languages like
L<HTML::Template::Compiled|HTML::Template::Compiled>, where you could say
<%IF_DEFINED obj.get_ELEMENT %>
<%LOOP obj.get_ELEMENT %>
...
<%/LOOP>
<%IF%>
=head1 HOW IT WORKS
=head2 Base classes
SOAP::WSDL::XSD provides a set of base classes for the construction of XML
SOAP::WSDL::XSD provides a set of base classes for the construction of XML
schema defined type classes.
=head3 Builtin types
=head3 Builtin types
SOAP::WSDL::XSD provides classes for all builtin XML Schema datatypes.
For a list and reference on these classes, see
For a list and reference on these classes, see
SOAP::WSDL::XSD::Typelib::Builtin.
=head3 Derivation classes
For derivation by list, the list derivation class
For derivation by list, the list derivation class
SOAP::WSDL::XSD::Typelib::Builtin::list exists.
Derivation by restriction is handled without the help of additional classes.
=head3 Element construction class
For the construction of element classes, the element superclass
SOAP::WSDL::XSD::Typelib::Element exists. All elements are ultimately derived
from this class. Elements may inherit from type classes, too - see
For the construction of element classes, the element superclass
SOAP::WSDL::XSD::Typelib::Element exists. All elements are ultimately derived
from this class. Elements may inherit from type classes, too - see
L</TRANSLATION RULES> for details.
=head3 complexType construction class
For the construction of complexType classes, the construction class
SOAP::WSDL::XSD::Typelib::ComplexType is provided. It provides a __factory
method for placing attributes in generated classes, and generating
For the construction of complexType classes, the construction class
SOAP::WSDL::XSD::Typelib::ComplexType is provided. It provides a __factory
method for placing attributes in generated classes, and generating
appropriate setter/getter accessors.
The setters are special: They handle complex data structures of any type
(meaning hash refs, list refs and objects, and any combination of them), as
The setters are special: They handle complex data structures of any type
(meaning hash refs, list refs and objects, and any combination of them), as
long as their structure matches the expected structure.
=head1 TRANSLATION RULES
@@ -86,72 +112,72 @@ TODO add more elaborate description
=head3 element with type attribute
Elements defined by referencing a builtin or user defined type inherit
Elements defined by referencing a builtin or user defined type inherit
from SOAP::WSDL::XSD::Typelib::Element and from the corresponding type class.
Element Type
Element Type
base class class
^ ^
| |
------------
------------
|
Element type="" class
Element type="" class
=head3 element with ref attribute
Elements defined by referencing another element inherit from the
Elements defined by referencing another element inherit from the
corresponding element class.
referenced Element class
^
|
Element ref="" class
Element ref="" class
=head3 element with atomic simpleType
Elements defined by a atomic simpleType from
Elements defined by a atomic simpleType from
SOAP::WSDL::XSD::Typelib::Element and from the base type of the atomic type.
Element atomic Type
Element atomic Type
base class base class
^ ^
| |
--------------
--------------
|
element simpleType class
element simpleType class
=head3 element with atomic complexType
Elements defined with a atomic complexType inherit from
SOAP::WSDL::XSD::Typelib::Element and from
Elements defined with a atomic complexType inherit from
SOAP::WSDL::XSD::Typelib::Element and from
SOAP::WSDL::XSD::Typelib::ComplexType.
Element complexType
base class base class
^ ^
| |
--------------
--------------
|
element complexType class
element complexType class
=head2 complexType
TODO add more elaborate description
Some content models are not implemented yet. The content models
Some content models are not implemented yet. The content models
implemented are described below.
=head3 complexType with "all" variety
Complex types with "all" variety inherit from
SOAP::WSDL::XSD::Typelib::ComplexType, and call it's factory method for
Complex types with "all" variety inherit from
SOAP::WSDL::XSD::Typelib::ComplexType, and call it's factory method for
creating fields and accessors/mutators for the complexType's elements.
All element's type classes are loaded. Complex type classes have a "has a"
All element's type classes are loaded. Complex type classes have a "has a"
relationship to their element fields.
Element fields may either be element classes (for element ref="") or type
classes (for element type=""). No extra element classes are created for
Element fields may either be element classes (for element ref="") or type
classes (for element type=""). No extra element classes are created for
a complexType's elements.
complexType
@@ -163,8 +189,8 @@ a complexType's elements.
element name="a" ------------> Element or type class object
element name="b" ------------> Element or type class object
The implementation for all does enforce the order of elements as described
in the WSDL, even though this is not required by the XML Schema
The implementation for all does enforce the order of elements as described
in the WSDL, even though this is not required by the XML Schema
specification.
=head3 complexType with "sequence" variety
@@ -173,43 +199,43 @@ The implementation of the "sequence" variety is the same as for all.
=head3 complexType with "choice" variety
The implementation for choice currently is the same as for all - which means,
no check for occurence are made.
The implementation for choice currently is the same as for all - which means,
no check for occurrence are made.
=head3 complexType with complexContent content model
Note that complexType classes with complexContent content model don't exhibit
their type via the xsi:type attribute yet, so they currently cannot be used
Note that complexType classes with complexContent content model don't exhibit
their type via the xsi:type attribute yet, so they currently cannot be used
as a replacement for their base type.
SOAP::WSDL's XSD deserializer backend does not recognize the xsi:type=""
SOAP::WSDL's XSD deserializer backend does not recognize the xsi:type=""
attribute either yet.
=over
=item * restriction variety
ComplexType classes with restriction variety inherit from their base type.
ComplexType classes with restriction variety inherit from their base type.
No additional processing or content checking is performed yet.
complexType
base type class
^
|
complexType
complexType
restriction
=item * extension variety
ComplexType classes with extension variety inherit from the XSD base
complexType class and from their base type.
ComplexType classes with extension variety inherit from the XSD base
complexType class and from their base type.
Extension classes are checked for (re-)defining all elements of their parent
Extension classes are checked for (re-)defining all elements of their parent
class.
Note that a derived type's elements (=properties) overrides the getter /
setter methods for all inherited elements. All object data is stored in the
derived type's class, not in the defining class (See L<Class::Std> for a
Note that a derived type's elements (=properties) overrides the getter /
setter methods for all inherited elements. All object data is stored in the
derived type's class, not in the defining class (See L<Class::Std> for a
discussion on inside out object data storage).
No additional processing or content checking is performed yet.
@@ -220,7 +246,7 @@ No additional processing or content checking is performed yet.
| |
-----------------
|
complexType
complexType
extension
=back
@@ -229,36 +255,60 @@ No additional processing or content checking is performed yet.
TODO add more elaborate description
Some derivation methods are not implemented yet. The derivation methods
Some derivation methods are not implemented yet. The derivation methods
implemented are described below.
=head3 Derivation by list
Derivation by list is implemented by inheriting from both the base type and
Derivation by list is implemented by inheriting from both the base type and
SOAP::WSDL::XSD::Typelib::XSD::list.
=head3 Derivation by restriction
Derivation by restriction is implemented by inheriting from a base type and
Derivation by restriction is implemented by inheriting from a base type and
applying the required restrictions.
=head1 FACETS
XML Schema facets are not implemented yet.
They will probably implemented some day by putting constant methods into
They will probably implemented some day by putting constant methods into
the correspondent classes.
=head1 ATTRIBUTES
XML attributes are not implemented yet. If you have a good idea on how to
XML attributes are not implemented yet. If you have a good idea on how to
implement them, feel free to email me a proposal.
=head1 CAVEATS
=over
=item * START and BUILD are not being called
In contrast to "normal" Class::Std based objects, the classes of the
SOAP::WSDL::XSD::Typelib:: hierarchy (and all type and element classes
generated by SOAP::WSDL) override Class::Std's constructor for performance
reasons.
If you inherit from such a class and place a START or BUILD method in it,
it will not get called - at least not unless you place something like this
at the top of you code:
use Class::Std::Storable;
In this case, Class::Std::Storable will export a new() method into your class,
which in turn calls START and BUILD.
The constructors of all SOAP::WSDL::XSD::Typelib:: classes don't !
=back
=head1 BUGS AND LIMITATIONS
The following XML Schema declaration elements are not supported yet:
=over
=over
=item * Declaration elements
@@ -293,10 +343,10 @@ The following XML Schema declaration elements are not supported yet:
=back
The following XML Schema declaration elements are supported, but have no
The following XML Schema declaration elements are supported, but have no
effect yet:
=over
=over
=item * Factes
@@ -323,11 +373,19 @@ effect yet:
Copyright 2007 Martin Kutter.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 390 $
$LastChangedBy: kutterma $
$Id: Client.pm 390 2007-11-16 22:18:32Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
=cut

View File

@@ -2,7 +2,7 @@ package SOAP::WSDL::Operation;
use strict;
use warnings;
use Class::Std::Storable;
use base qw/SOAP::WSDL::Base/;
use base qw(SOAP::WSDL::Base);
my %operation_of :ATTR(:name<operation> :default<()>);
my %input_of :ATTR(:name<input> :default<[]>);

View File

@@ -22,11 +22,11 @@ sub serialize
if ($item_name = $self->get_type() ) {
# resolve type
my ($prefix, $localname) = split /:/ , $item_name, 2;
my $type = $typelib->find_type( $ns_map{ $prefix }, $localname )
my $type = $typelib->find_type( $ns_map{ $prefix }, $localname)
or die "type $item_name , $ns_map{ $prefix } not found";
my $name = $self->get_name();
return $type->serialize( $name, $data->{ $name }, $opt );
return $type->serialize( $name, $data->{ $name }, $opt );
}
elsif ( $item_name = $self->get_element() ) {
my ($prefix, $localname) = split /:/ , $item_name, 2;

View File

@@ -15,7 +15,7 @@ my %attributes_of :ATTR();
# Function factory - we could be writing this method for all %attribute
# keys, too, but that's just C&P (eehm, Copy & Paste...)
foreach my $method(keys %attributes_of ) {
no strict qw/refs/;
no strict qw(refs); ## no critic ProhibitNoStrict
# ... btw, we mean this method here...
*{ "find_$method" } = sub {

View File

@@ -24,13 +24,13 @@ __PACKAGE__->_factory(
faultcode => \%faultcode_of,
faultstring => \%faultstring_of,
faultactor => \%faultactor_of,
detail => \%detail_of,
detail => \%detail_of,
},
{
faultcode => 'SOAP::WSDL::XSD::Typelib::Builtin::QName',
faultstring => 'SOAP::WSDL::XSD::Typelib::Builtin::string',
faultactor => 'SOAP::WSDL::XSD::Typelib::Builtin::anyURI',
detail => 'SOAP::WSDL::XSD::Typelib::Builtin::anyType',
detail => 'SOAP::WSDL::XSD::Typelib::Builtin::anyType',
}
);
@@ -58,7 +58,7 @@ SOAP::WSDL::SOAP::Typelib::Fault11 - SOAP 1.1 Fault class
Models a SOAP 1.1 Fault.
SOAP::WSDL::SOAP::Typelib::Fault11 objects are false in boolean context
SOAP::WSDL::SOAP::Typelib::Fault11 objects are false in boolean context
and serialize to XML on stringification.
This means you can do something like:
@@ -88,15 +88,23 @@ Getter/setter for object's the faultactor property.
Getter/setter for detail object's detail property.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2007 Martin Kutter.
Copyright 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Fault11.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/SOAP/Typelib/Fault11.pm $
=cut

View File

@@ -4,15 +4,15 @@ use strict;
use warnings;
use Class::Std::Storable;
our $VERSION='2.00_21';
our $VERSION='2.00_24';
my $SOAP_NS = 'http://schemas.xmlsoap.org/soap/envelope/';
my $XML_INSTANCE_NS = 'http://www.w3.org/2001/XMLSchema-instance';
sub serialize {
my ($self, $args_of_ref) = @_;
my $opt = $args_of_ref->{ options };
my $opt = $args_of_ref->{ options };
if (not $opt->{ namespace }->{ $SOAP_NS })
{
@@ -44,10 +44,10 @@ sub serialize {
sub serialize_header {
my ($self, $name, $data, $opt) = @_;
# header is optional. Leave out if there's no header data
return q{} if not $data;
return join ( q{},
return join ( q{},
"<$opt->{ namespace }->{ $SOAP_NS }\:Header>",
"$data",
"</$opt->{ namespace }->{ $SOAP_NS }\:Header>",
@@ -57,11 +57,66 @@ sub serialize_header {
sub serialize_body {
my ($self, $name, $data, $opt) = @_;
# Body is NOT optional. Serialize to empty body
# Body is NOT optional. Serialize to empty body
# if we have no data.
return join ( q{},
return join ( q{},
"<$opt->{ namespace }->{ $SOAP_NS }\:Body>",
defined $data ? "$data" : (),
"</$opt->{ namespace }->{ $SOAP_NS }\:Body>",
);
}
__END__
=pod
=head1 NAME
SOAP:WSDL::Serializer::XSD - Serializer for SOAP::WSDL::XSD::Typelib:: objects
=head1 DESCRIPTION
This is the default serializer for SOAP::WSDL::Client and Interface classes
generated by SOAP::WSDL
It may be used as a template for creating custom serializers.
See L<SOAP::WSDL::Factory::Serializer|SOAP::WSDL::Factory::Serializer> for
details on that.
=head1 METHODS
=head2 serialize
Creates a SOAP envelope based on the body and header arguments passed.
Sets SOAP namespaces.
=head2 serialize_body
Serializes a message body to XML
=head2 serialize_header
Serializes a message header to XML
=head1 LICENSE AND COPYRIGHT
Copyright (c) 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: XSD.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Serializer/XSD.pm $
=cut

View File

@@ -6,7 +6,7 @@ use base qw(LWP::UserAgent);
SUBFACTORY: {
no strict qw(refs);
foreach my $method ( qw(code message status is_success) ) {
*{ $method } = sub {
*{ $method } = sub {
my $self = shift;
return $self->{ $method } if not @_;
return $self->{ $method } = shift;
@@ -19,8 +19,8 @@ sub send_receive {
my ($envelope, $soap_action, $endpoint, $encoding, $content_type) =
@parameters{qw(envelope action endpoint encoding content_type)};
$encoding = defined($encoding)
? 'utf8'
$encoding = defined($encoding)
? 'utf8'
: lc($encoding);
# what's this all about?
@@ -40,7 +40,7 @@ sub send_receive {
# use bytes is lexically scoped
my $bytelength = do { use bytes; length $envelope };
$envelope = pack('C0A*', $envelope)
$envelope = pack('C0A*', $envelope)
if length($envelope) != $bytelength;
my $request = HTTP::Request->new( 'POST',
@@ -50,15 +50,15 @@ sub send_receive {
'SOAPAction', $soap_action,
],
$envelope );
my $response = $self->request( $request );
$self->code( $response->code);
$self->message( $response->message);
$self->is_success($response->is_success);
$self->status($response->status_line);
return $response->content();
return $response->content();
}
1;
@@ -71,14 +71,14 @@ SOAP::WSDL::Transport::HTTP - Fallback http(s) transport class
=head1 DESCRIPTION
Provides a thin transport class used by SOAP::WSDL::Transport when
Provides a thin transport class used by SOAP::WSDL::Transport when
SOAP::Lite is not available.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright (c) 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
@@ -87,9 +87,9 @@ Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 288 $
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: HTTP.pm 288 2007-09-29 19:34:20Z kutterma $
$Id: HTTP.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Transport/HTTP.pm $
=cut

View File

@@ -4,23 +4,23 @@ use warnings;
use Class::Std::Storable;
use SOAP::WSDL::Factory::Transport;
our $VERSION = '2.00_17';
our $VERSION = '2.00_17';
SOAP::WSDL::Factory::Transport->register( http => __PACKAGE__ );
SOAP::WSDL::Factory::Transport->register( https => __PACKAGE__ );
my %code_of :ATTR(:name<code> :default<()>);
my %status_of :ATTR(:name<status> :default<()>);
my %message_of :ATTR(:name<message> :default<()>);
my %is_success_of :ATTR(:name<is_success> :default<()>);
my %code_of :ATTR(:name<code> :default<()>);
my %status_of :ATTR(:name<status> :default<()>);
my %message_of :ATTR(:name<message> :default<()>);
my %is_success_of :ATTR(:name<is_success> :default<()>);
{
no warnings qw(redefine);
sub new {
my $class = shift;
return bless \my ($o), $class;
}
}
}
# create methods normally inherited from SOAP::Client
@@ -53,18 +53,18 @@ SOAP::WSDL::Transport::Test - Loopback transport class for SOAP::WSDL
=head1 DESCRIPTION
SOAP::WSDL::Transport::Loopback is a loopback test transport backend for
SOAP::WSDL.
SOAP::WSDL::Transport::Loopback is a loopback test transport backend for
SOAP::WSDL.
When SOAP::WSDL::Transport::Loopback is used as transport backend, the
request is returned as response. No data ever goes over the wire.
When SOAP::WSDL::Transport::Loopback is used as transport backend, the
request is returned as response. No data ever goes over the wire.
This is particularly useful for testing SOAP::WSDL plugins and applications.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright (c) 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR

View File

@@ -4,7 +4,7 @@ use warnings;
use Class::Std::Storable;
use SOAP::WSDL::Factory::Transport;
our $VERSION = '2.00_14';
our $VERSION = '2.00_14';
SOAP::WSDL::Factory::Transport->register( http => __PACKAGE__ );
SOAP::WSDL::Factory::Transport->register( https => __PACKAGE__ );
@@ -32,27 +32,27 @@ sub send_receive {
$filename =~s{ \A(:?'|") }{}xms;
$filename =~s{ (:?'|")\z }{}xms;
$filename =~s{ \A [^:]+ : (:? /{2})? }{}xms;
$filename = join '/', $base_dir_of{ ident $self }, "$filename.xml";
if (not -r $filename) {
if (not -r $filename) {
warn "cannot access $filename";
$self->set_code( 500 );
$self->set_message( "Failed" );
$self->set_is_success(0);
$self->set_status("500 Failed");
return;
return;
}
open my $fh, '<', $filename or die "cannot open $filename: $!";
binmode $fh;
my $response = <$fh>;
close $fh or die "cannot close $filename: $!";
close $fh or die "cannot close $filename: $!";
$self->set_code( 200 );
$self->set_message( "OK" );
$self->set_is_success(1);
$self->set_status("200 OK");
$self->set_status("200 OK");
return $response;
}
@@ -73,21 +73,21 @@ SOAP::WSDL::Transport::Test - Test transport class for SOAP::WSDL
=head1 DESCRIPTION
SOAP::WSDL::Transport::Test is a file-based test transport backend for
SOAP::WSDL.
SOAP::WSDL::Transport::Test is a file-based test transport backend for
SOAP::WSDL.
When SOAP::WSDL::Transport::Test is used as transport backend, the reponse is
read from a XML file and the request message is discarded. This is particularly
useful for testing SOAP::WSDL plugins.
When SOAP::WSDL::Transport::Test is used as transport backend, the reponse is
read from a XML file and the request message is discarded. This is
particularly useful for testing SOAP::WSDL plugins.
=head2 Filename resolution
SOAP::WSDL::Transport makes up the response XML file name from the SOAPAction
SOAP::WSDL::Transport makes up the response XML file name from the SOAPAction
of the request. The following filename is used:
base_dir / soap_action .xml
The protocol scheme (e.g. http:) and two heading slashes (//) are stripped from
The protocol scheme (e.g. http:) and two heading slashes (//) are stripped from
the soap_action.
base_dir defaults to '.'
@@ -105,14 +105,14 @@ Examples:
=head2 set_base_dir
Sets the base directory SOAP::WSDL::Transport::Test should look for response
Sets the base directory SOAP::WSDL::Transport::Test should look for response
files.
=head1 LICENSE
=head1 LICENSE AND COPYRIGHT
Copyright 2004-2007 Martin Kutter.
Copyright (c) 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR

View File

@@ -1,4 +1,6 @@
package SOAP::WSDL::TypeLookup;
use strict;
use warnings;
my %TYPES = (
# wsdl:
@@ -100,7 +102,7 @@ my %TYPES = (
},
notation => {
type => 'SKIP', # not implemented yet
},
},
annotation => {
type => 'SKIP', # not implemented yet
},
@@ -144,7 +146,7 @@ my %TYPES = (
type => 'METHOD',
method => 'set_list',
},
union => {
union => {
type => 'METHOD',
method => 'set_union',
},
@@ -157,7 +159,7 @@ my %TYPES = (
method => 'set_flavor',
value => 'group',
},
all => {
all => {
type => 'METHOD',
method => 'set_flavor',
value => 'all',
@@ -175,10 +177,11 @@ my %TYPES = (
},
);
sub lookup {
my $self = shift;
my $namespace = shift || 'http://schemas.xmlsoap.org/wsdl/';
my $name = shift;
return $TYPES{ $namespace }->{ $name };
my $self = shift;
my $namespace = shift || 'http://schemas.xmlsoap.org/wsdl/';
my $name = shift;
return $TYPES{ $namespace }->{ $name };
}
1;

View File

@@ -9,7 +9,7 @@ sub serialize {
my $xml;
$opt->{ indent } ||= "";
$opt->{ attributes } ||= [];
$xml .= $opt->{ indent } if ($opt->{ readable });
$xml .= '<' . join ' ', $name, @{ $opt->{ attributes } };
if ( $opt->{ autotype }) {
@@ -20,7 +20,7 @@ sub serialize {
. $self->get_name() . '"' if ($self->get_name() );
}
if (defined $value) {
if (defined $value) {
$xml .= '>';
$xml .= "$value";
$xml .= '</' . $name . '>' ;

View File

@@ -53,9 +53,9 @@ sub set_extension {
}
sub init {
my $self = shift;
my @args = @_;
$self->SUPER::init( @args );
my $self = shift;
my @args = @_;
$self->SUPER::init( @args );
}
sub serialize {
@@ -70,12 +70,12 @@ sub serialize {
if ( $opt->{ qualify } ) {
$opt->{ attributes } = [ ' xmlns="' . $self->get_targetNamespace .'"' ];
delete $opt->{ qualify };
}
}
$xml .= join q{ } , "<$name" , @{ $opt->{ attributes } };
delete $opt->{ attributes }; # don't propagate...
if ( $opt->{ autotype }) {
my $ns = $self->get_targetNamespace();
my $prefix = $opt->{ namespace }->{ $ns }
@@ -84,32 +84,31 @@ sub serialize {
if ($self->get_name() );
}
$xml .= '>';
$xml .= "\n" if ( $opt->{ readable } ); # add linebreak
if ( ($flavor eq "sequence") or ($flavor eq "all") )
{
$xml .= "\n" if ( $opt->{ readable } ); # add linebreak
if ( ($flavor eq "sequence") or ($flavor eq "all") ) {
$opt->{ indent } .= "\t";
for my $element (@{ $self->get_element() }) {
# might be list - listify
$value = [ $value ] if not ref $value eq 'ARRAY';
for my $single_value (@{ $value }) {
my $element_value;
if (blessed $single_value) {
my $element_value;
if (blessed $single_value) {
my $method = 'get_' . $element->get_name();
$element_value = $single_value->$method();
$element_value = $single_value->$method();
}
else {
else {
$element_value = $single_value->{ $element->get_name() };
}
$element_value = [ $element_value ]
$element_value = [ $element_value ]
if not ref $element_value eq 'ARRAY';
$xml .= join q{}
, map { $element->serialize( undef, $_, $opt ) }
@{ $element_value };
$xml .= join q{}
, map { $element->serialize( undef, $_, $opt ) }
@{ $element_value };
}
}
$opt->{ indent } =~s/\t$//;
$opt->{ indent } =~s/\t$//;
}
else {
die "sorry, we just handle all and sequence types yet...";

View File

@@ -57,7 +57,7 @@ sub serialize {
if ( $opt->{ qualify } ) {
$opt->{ attributes } = [ ' xmlns="' . $self->get_targetNamespace .'"' ];
}
}
# set default and fixed - fixed overrides everything,
@@ -93,9 +93,9 @@ sub serialize {
# lookup type
my ($prefix, $localname) = split /:/ , $self->get_type();
my $ns = $ns_map{ $prefix };
$type = $typelib->find_type(
$ns, $localname
);
$type = $typelib->find_type(
$ns, $localname
);
# safety check
die "no type for $prefix:$localname $ns_map{$prefix}" if (not $type);
@@ -105,4 +105,3 @@ sub serialize {
1;

View File

@@ -8,55 +8,90 @@ use base qw(SOAP::WSDL::XSD::Schema);
# all builtin types - add validation (e.g. content restrictions) later...
my %BUILTINS = (
'string' => {},
'boolean' => {},
'decimal' => {},
'dateTime' => {},
'float' => {},
'double' => {},
'duration' => {},
'time' => {},
'date' => {},
'gYearMonth' => {},
'gYear' => {},
'gMonthDay' => {},
'gDay' => {},
'gMonth' => {},
'hexBinary' => {},
'base64Binary' => {},
'anyURI' => {},
'QName' => {},
'NOTATION' => {},
'integer' => {},
'nonPositiveInteger' => {},
'nonNegativeInteger' => {},
'positiveInteger' => {},
'negativeInteger' => {},
'string' => {},
'boolean' => {},
'decimal' => {},
'dateTime' => {},
'float' => {},
'double' => {},
'duration' => {},
'time' => {},
'date' => {},
'gYearMonth' => {},
'gYear' => {},
'gMonthDay' => {},
'gDay' => {},
'gMonth' => {},
'hexBinary' => {},
'base64Binary' => {},
'anyURI' => {},
'QName' => {},
'NOTATION' => {},
'integer' => {},
'nonPositiveInteger' => {},
'nonNegativeInteger' => {},
'positiveInteger' => {},
'negativeInteger' => {},
'long' => {},
'int' => {},
'unsignedInt' => {},
'short' => {},
'unsignedShort' => {},
'byte' => {},
'unsignedByte' => {},
'normalizedString' => {},
'token' => {},
'NMTOKEN' => {},
'int' => {},
'unsignedInt' => {},
'short' => {},
'unsignedShort' => {},
'byte' => {},
'unsignedByte' => {},
'normalizedString' => {},
'token' => {},
'NMTOKEN' => {},
);
sub START {
my $self = shift;
my @args = @_;
my $self = shift;
my @args = @_;
while (my ($name, $value) = each %BUILTINS )
{
$self->push_type( SOAP::WSDL::XSD::Builtin->new({
while (my ($name, $value) = each %BUILTINS )
{
$self->push_type( SOAP::WSDL::XSD::Builtin->new({
name => $name,
targetNamespace => 'http://www.w3.org/2001/XMLSchema',
} )
);
}
);
}
return $self;
}
1;
=pod
=head1 NAME
SOAP:WSDL::XSD::Schema::Builtin - Provides builtin XML Schema datatypes for parsing WSDL
=head1 DESCRIPTION
Used internally by SOAP::WSDL's WSDL parser.
See <SOAP::WSDL::XSD::Typelib::Builtin|SOAP::WSDL::XSD::Typelib::Builtin> for
SOAP::WSDL::XSD's builtin XML Schema datatypes.
=head1 LICENSE AND COPYRIGHT
Copyright (c) 2007 Martin Kutter. All rights reserved.
This file is part of SOAP-WSDL. You may distribute/modify it under
the same terms as perl itself
=head1 AUTHOR
Martin Kutter E<lt>martin.kutter fen-net.deE<gt>
=head1 REPOSITORY INFORMATION
$Rev: 391 $
$LastChangedBy: kutterma $
$Id: Builtin.pm 391 2007-11-17 21:56:13Z kutterma $
$HeadURL: http://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/XSD/Schema/Builtin.pm $
=cut

View File

@@ -61,10 +61,10 @@ sub serialize {
my $value = shift;
my $opt = shift;
my $ident = ident $self;
$opt->{ attributes } ||= [];
$opt->{ indent } ||= q{};
return $self->_serialize_single($name, $value , $opt)
if ( $flavor_of{ $ident } eq 'restriction'
or $flavor_of{ $ident } eq 'union'
@@ -81,7 +81,7 @@ sub serialize {
sub _serialize_single {
my ($self, $name, $value, $opt) = @_;
my $xml = '';
$xml .= $opt->{ indent } if ($opt->{ readable }); # add indentation
$xml .= $opt->{ indent } if ($opt->{ readable }); # add indentation
$xml .= '<' . join ' ', $name, @{ $opt->{ attributes } };
if ( $opt->{ autotype }) {
my $ns = $self->get_targetNamespace();
@@ -89,10 +89,10 @@ sub _serialize_single {
|| die 'No prefix found for namespace '. $ns;
$xml .= ' type="' . $prefix . ':' . $self->get_name() .'"';
}
# nillabel ?
return $xml .'/>' if not defined $value;
$xml .= join q{}, '>' , $value , '</' , $name , '>';
$xml .= "\n" if ($opt->{ readable });
return $xml;

View File

@@ -64,19 +64,21 @@ SOAP::WSDL::XSD::Typelib::Builtin - Built-in XML Schema datatypes
=head1 DESCRIPTION
This module implements all builtin Types from the XML schema specification.
The SOAP::WSDL::XSD::Typelib::Builtin hierarchy implements all builtin types
from the XML schema specification.
Objects of a class may be filled with values and serialize correctly.
All XML schema derived types inherit from
SOAP::WSDL::XSD::Typelib::Builtin::anyType.
These basic type classes are most useful when used as element or simpleType
base classes.
The datatypes classes themselves are split up into
SOAP::WSDL::XSD::Typelib::Builtin::* modules.
Using SOAP::WSDL::XSD::Typelib::Builtin uses all of the builtin datatype
Using SOAP::WSDL::XSD::Typelib::Builtin uses all of the builtin datatype
classes.
All builtin types feature common behaviour described below in
L</OVERLOADED OPERATORS>
=head1 EXAMPLES
my $bool = SOAP::WSDL::XSD::Typelib::Builtin::bool->new({ value => 0} );
@@ -88,7 +90,7 @@ classes.
package MySimpleType;
use SOAP::WSDL::XSD::Typelib::Builtin;
use SOAP::WSDL::XSD::Typelib::SimpleType;
use base qw(SOAP::WSDL::XSD::Typelib::SimpleType
SOAP::WSDL::XSD::Typelib::Builtin::list
SOAP::WSDL::XSD::Typelib::Builtin::string
@@ -177,6 +179,36 @@ The boolean class returns 0 or 1 in numeric context.
decimal, float and double (and derived classes) return their value in
numeric context.
=item * arrayification (@{})
When accessed as a list ref, objects of all classes return a list ref with
the object itself as single element.
This is most useful for writing loops without additional conversions,
especially in mini-languages found in templating systems or the like, which
may not natively support converting to list refs.
Instead of writing something like
my $value = $complexType->get_ELEMENT;
$value = ref $value eq 'ARRAY' ? $value : [ $value ];
for (@{ $value }) { ... }
you can just write
for (@{ $complexType->get_ELEMENT }) {...}
Note that complexTypes with undef elements still return undef when accessing
an undefined element, so when an element may be empty you still have to write
something like:
my $value = $complexType->get_ELEMENT();
if (defined $value) {
for (@{ $value }) {
...
}
}
=back
=head1 Subclasses
@@ -205,14 +237,14 @@ Returns true/false in boolean context.
Returns 1 / 0 in numeric context.
boolean objects have a special method for deleteing their value, because
boolean objects have a special method for deleteing their value, because
calling C<setl_value(undef)> results in the value being set to false.
$obj->delete_value();
=head2 SOAP::WSDL::XSD::Typelib::Builtin::byte
=head2 SOAP::WSDL::XSD::Typelib::Builtin::byte
byte integer objects.
byte integer objects.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::date
@@ -222,12 +254,12 @@ date values are automatically converted into XML date strings during setting:
The time zone is set to the local time zone if not included.
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the time part will be ignored. Note that
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the time part will be ignored. Note that
set_value is around 100 times slower when setting non-XML-time strings
When setting dates before the beginning of the epoch (negative UNIX timestamp),
you should use the XML date string format for setting dates. The behaviour of
When setting dates before the beginning of the epoch (negative UNIX timestamp),
you should use the XML date string format for setting dates. The behaviour of
Date::Parse for dates before the epoch is system dependent.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::dateTime
@@ -236,19 +268,19 @@ dateTime values are automatically converted into XML dateTime strings during set
YYYY-MM-DDThh:mm:ss.nnnnnnn+zz:zz
The fraction of seconds (nnnnnnn) part is optional. Fractions of seconds may
The fraction of seconds (nnnnnnn) part is optional. Fractions of seconds may
be given with arbitrary precision
The fraction of seconds part is excluded in converted values, as it would always be 0.
All input variants supported by Date::Parse are supported. Note that
All input variants supported by Date::Parse are supported. Note that
set_value is around 100 times slower when setting non-XML-time strings
=head2 SOAP::WSDL::XSD::Typelib::Builtin::decimal
decimal is the base of all non-float numbers
=head2 SOAP::WSDL::XSD::Typelib::Builtin::double
=head2 SOAP::WSDL::XSD::Typelib::Builtin::double
=head2 SOAP::WSDL::XSD::Typelib::Builtin::duration
@@ -300,8 +332,8 @@ Derived by SOAP::WSDL::XSD::Typelib::Builtin::list.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::normalizedString
Tab, newline and carriage return characters are replaced by whitespace in
set_value.
Tab, newline and carriage return characters are replaced by whitespace in
set_value.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::NOTATION
@@ -313,7 +345,7 @@ set_value.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::string
String values are XML-escaped on serialization.
String values are XML-escaped on serialization.
The following characters are escaped: <, >, &
@@ -324,12 +356,12 @@ time values are automatically converted into XML time strings during setting:
hh:mm:ss.nnnnnnn+zz:zz
hh:mm:ss+zz:zz
The time zone is set to the local time zone if not included. The optional
The time zone is set to the local time zone if not included. The optional
nanoseconds part is not included in converted values, as it would always be 0.
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the date part will be ignored. Note that
set_value is around 100 times slower when setting non-XML-time strings
All input variants supported by Date::Parse are supported. You may even pass
in dateTime strings - the date part will be ignored. Note that
set_value is around 100 times slower when setting non-XML-time strings.
=head2 SOAP::WSDL::XSD::Typelib::Builtin::token
@@ -347,10 +379,10 @@ set_value is around 100 times slower when setting non-XML-time strings
=item * set_value
In contrast to Class::Std-generated mutators (setters), set_value does
In contrast to Class::Std-generated mutators (setters), set_value does
not return the last value.
This is for speed reasons: SOAP::WSDL never needs to know the last value
This is for speed reasons: SOAP::WSDL never needs to know the last value
when calling set_calue, but calls it over and over again...
=back

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -11,9 +11,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -16,10 +16,10 @@ sub set_value { $value_of{ ident $_[0] } = $_[1] }
# use $_[n] for speed.
# This is less readable, but notably faster.
#
# use postfix-if for speed. This is slightly faster, as it saves
# use postfix-if for speed. This is slightly faster, as it saves
# perl from creating a pad (variable context).
#
# The methods below may get called zillions of times, so
# The methods below may get called zillions of times, so
# every little statement matters...
sub serialize {
@@ -29,7 +29,7 @@ sub serialize {
return join q{}
, $_[0]->start_tag($_[1], $value_of{ $ident })
, $value_of{ $ident }
, $_[0]->end_tag($_[1]);
, $_[0]->end_tag($_[1]);
}
sub as_bool :BOOLIFY {

View File

@@ -6,14 +6,14 @@ use Class::Std::Storable;
sub get_xmlns { 'http://www.w3.org/2001/XMLSchema' };
# use $_[1] for performance
sub start_tag {
sub start_tag {
my $opt = $_[1] ||= {};
return '<' . $opt->{name} . ' >' if $opt->{ name };
return q{}
}
# use $_[1] for performance
sub end_tag {
sub end_tag {
return $_[1] && defined $_[1]->{ name }
? "</$_[1]->{name} >"
: q{};
@@ -25,6 +25,10 @@ sub serialize_qualified :STRINGIFY {
return $_[0]->serialize( { qualified => 1 } );
}
sub as_list :ARRAYIFY {
return [ $_[0] ];
}
Class::Std::initialize(); # make :STRINGIFY overloading serializable
1;

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -11,9 +11,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )
@@ -24,8 +24,8 @@ BEGIN {
}
# XML Schema facets. We don't know how to implement them yet, but they're
# her, just in case you wanted to know.
# XML Schema facets. We don't know how to implement them yet, but they're
# here, just in case you wanted to know.
#my %length_of :ATTR(:name<length> :default<()>);
#my %minLength_of :ATTR(:name<minLength> :default<()>);
#my %maxLength_of :ATTR(:name<maxLength> :default<()>);

View File

@@ -15,9 +15,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -13,9 +13,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )
@@ -30,25 +30,25 @@ sub set_value {
# use set_value from base class if we have a XML-DateTime format
#2037-12-31+01:00
if (
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
(:? [\+\-] \d{2} \: \d{2} )$
}xms
}xms
) {
$_[0]->SUPER::set_value($_[1])
}
# converting a date is hard work: It needs a timezone, because
# 2007-12-30+12:00 and 2007-12-31-12:00 mean the same day - just in
# converting a date is hard work: It needs a timezone, because
# 2007-12-30+12:00 and 2007-12-31-12:00 mean the same day - just in
# different locations.
# strftime actually prints out the correct date, but always prints the
# strftime actually prints out the correct date, but always prints the
# local timezone with %z.
# So, if our timezone is not 0, we strftime it without timezone and
# So, if our timezone is not 0, we strftime it without timezone and
# append it by hand by the following formula:
# The timezone hours are the int (timesone seconds / 3600)
# The timezone minutes (if someone ever specifies something like that)
# are int( (seconds % 3600) / 60 )
# The timezone minutes (if someone ever specifies something like that)
# are int( (seconds % 3600) / 60 )
# say, int( (seconds modulo 3600) / 60 )
#
# If we have no timezone (meaning the timezone is
# If we have no timezone (meaning the timezone is
else {
# strptime sets empty values to undef - and strftime doesn't like that...
my @time_from = strptime($_[1]);
@@ -57,9 +57,9 @@ sub set_value {
# use Data::Dumper;
# warn Dumper \@time_from, sprintf('%+03d%02d', $time_from[6] / 3600, $time_from[6] % 60 );
my $time_str = defined $time_zone_seconds
? strftime( '%Y-%m-%d', @time_from )
? strftime( '%Y-%m-%d', @time_from )
. sprintf('%+03d%02d', int($time_from[6] / 3600), int ( ($time_from[6] % 3600) / 60 ) )
: do {
: do {
strftime( '%Y-%m-%d%z', @time_from );
};
substr $time_str, -2, 0, ':';

View File

@@ -7,8 +7,8 @@ use Date::Parse;
use Date::Format;
# XML Schema facets. We don't know how to implement them yet, but they're
# her, just in case you wanted to know.
# XML Schema facets. We don't know how to implement them yet, but they're
# here, just in case you wanted to know.
#
#my %pattern_of :ATTR(:name<pattern> :default<()>);
#my %enumeration_of :ATTR(:name<enumeration> :default<()>);
@@ -26,9 +26,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )
@@ -43,17 +43,17 @@ sub set_value {
#2037-12-31T00:00:00.0000000+01:00
return if not $_[1];
return $_[0]->SUPER::set_value($_[1]) if (
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
$_[1] =~ m{ ^\d{4} \- \d{2} \- \d{2}
T \d{2} \: \d{2} \: \d{2} (:? \. \d{1,7} )?
[\+\-] \d{2} \: \d{2} $
}xms
}xms
);
# strptime sets empty values to undef - and strftime doesn't like that...
my @time_from = map { ! defined $_ ? 0 : $_ } strptime($_[1]);
return if not (@time_from);
undef $time_from[$#time_from];
my $time_str = strftime( '%Y-%m-%dT%H:%M:%S%z', @time_from );
substr $time_str, -2, 0, ':';
$_[0]->SUPER::set_value($time_str);

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -9,9 +9,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -9,9 +9,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

View File

@@ -10,9 +10,9 @@ BEGIN {
no warnings qw(redefine);
no strict qw(refs);
# Yes, I know it's ugly - but this is the fastest constructor to write
# Yes, I know it's ugly - but this is the fastest constructor to write
# for Class::Std-Style inside out objects..
*{ __PACKAGE__ . '::new' } = sub {
*{ __PACKAGE__ . '::new' } = sub {
my $self = bless \do { my $foo } , shift;
if (@_) {
$self->set_value( $_[0]->{ value } )

Some files were not shown because too many files have changed in this diff Show More