.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" ======================================================================== .\" .IX Title "SOAP::WSDL::Generator::Visitor 3pm" .TH SOAP::WSDL::Generator::Visitor 3pm "2018-05-05" "perl v5.26.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" SOAP::WSDL::Generator::Visitor \- SOAP::WSDL's Visitor\-based Code Generator .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\s-1SOAP::WSDL\s0 features 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. .SS "The Visitor Pattern" .IX Subsection "The Visitor Pattern" The Visitor design pattern is one of the object oriented design pattern described by [\s-1GHJV1995\s0]. .PP A Visitor is an object implementing some behaviour for a fixed set of classes, whose implementation would otherwise need to be scattered across those classes' implementations. .PP Visitors are usually combined with Iterators for traversing either a list or tree of objects. .PP 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 to be handled, whereas every class implements just one method (commonly named \&\*(L"access\*(R"), which does nothing more than calling a method on the reference given, with the self object as parameter. .PP 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 else you like). This can easily be implemented with a Visitor: .PP .Vb 2 \& 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(), "\en"; \& } \& \& package Person; \& use Class::Std; \& my %name : ATTR(:name :default); \& \& 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); \& } \& \& # will print \& Person name is Gamma \& Person name is Helm \& Person name is Johnson \& Person name is Vlissides .Ve .PP While using this pattern for just printing a list may look a bit over-sized, it may become handy if you need multiple output formats and different classes to operate on. .PP The main benefits using visitors are: .IP "\(bu" 4 Grouping related behaviour in one class .Sp 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. .IP "\(bu" 4 Cleaning up the data classes' implementations .Sp If classes holding data also implement several different output formats or other (otherwise unrelated) behaviour, they tend to get bloated. .IP "\(bu" 4 Adding behaviour is easy .Sp 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. .PP Of course, there are also drawbacks in the visitor pattern: .IP "\(bu" 4 Changes in the visited classes are expensive .Sp 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. .IP "\(bu" 4 The visited classes must expose all data required .Sp 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. .PP 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). .PP The Iterator decides which object to visit next. .SS "Why \s-1SOAP::WSDL\s0 uses the Visitor pattern for Code Generation" .IX Subsection "Why SOAP::WSDL uses the Visitor pattern for Code Generation" Code generation in \s-1SOAP::WSDL\s0 means generating various artefacts: .IP "\(bu" 4 Typemaps .Sp For every \s-1WSDL\s0 definition, a Typemap is created. The Typemap is used later as an aid in parsing the \s-1SOAP XML\s0 messages. .IP "\(bu" 4 Type Classes .Sp For every type defined in the \s-1WSDL\s0's schema, a Type Class is generated. .Sp These classes are instantiated later as a result of parsing \s-1SOAP XML\s0 messages. .IP "\(bu" 4 Interface Classes .Sp For every service, a interface class is generated. This class is later used by programmers accessing the service .IP "\(bu" 4 Documentation .Sp Both Type Classes and Interface Classes include documentation. Additional documentation may be generated as a hint for programmers, or later for mimicking .NET's .asmx example pages. .PP All these behaviours could well be (and have historically been) implemented in the classes holding the \s-1WSDL\s0 data. This made these classes rather bloated, and made it hard to change behaviour (like supporting \s-1SOAP\s0 Headers, supporting atomic types, and other features which were missing from early versions of \s-1SOAP::WSDL\s0). .PP Implementing these behaviours in Visitor classes eases adding new behaviours, and reducing the incompletenesses still inherent in \s-1SOAP::WSDL\s0's \s-1WSDL\s0 and \s-1XML\s0 schema implementation. .SS "Implementation" .IX Subsection "Implementation" \fIaccept\fR .IX Subsection "accept" .PP SOAP::WSDL::Base defines an accept method which expects a Visitor as only parameter. .PP The method visit_Foo_Bar is called on the visitor, with the self object as parameter. .PP The actual method name is constructed this way: .IP "\(bu" 4 \&\s-1SOAP::WSDL\s0 is stripped from the class name .IP "\(bu" 4 All remaining :: s are replaced by _ .PP Example: .PP When visiting a SOAP::WSDL::XSD::ComplexType object, the method visit_XSD_ComplexType is called on the visitor. .SS "Writing your own visitor" .IX Subsection "Writing your own visitor" \&\s-1SOAP::WSDL\s0 eases writing your own visitor. This might be required if you need some special output format from a \s-1WSDL\s0 file or want to feed your own serializer/deserializer pair with custom configuration data. Or maybe you want to generate C# code from it... .PP To write your own code generating visitor, you should subclass SOAP::WSDL::Generator::Visitor. It implements (empty) default methods for all \&\s-1SOAP::WSDL\s0 data classes: .IP "\(bu" 4 visit_Definitions .IP "\(bu" 4 visit_Binding .IP "\(bu" 4 visit_Message .IP "\(bu" 4 visit_Operation .IP "\(bu" 4 visit_OpMessage .IP "\(bu" 4 visit_Part .IP "\(bu" 4 visit_Port .IP "\(bu" 4 visit_PortType .IP "\(bu" 4 visit_Service .IP "\(bu" 4 visit_SoapOperation .IP "\(bu" 4 visit_Types .IP "\(bu" 4 visit_XSD_Schema .IP "\(bu" 4 visit_XSD_ComplexType .IP "\(bu" 4 visit_XSD_Element .IP "\(bu" 4 visit_XSD_SimpleType .PP In your Visitor, you must implement visit_Foo methods for all classes you wish to visit. .PP The SOAP::WSDL::Generator::Visitor implementations include part of 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. .PP Letting a visitor implementing its own Iterator visit a \s-1WSDL\s0 definition is as easy as writing something like this: .PP .Vb 3 \& my $visitor = MyVisitor\->new(); \& my $parser = SOAP::WSDL::Expat::WSDLParser\->new(); \& my $definitions = $parser\->parse_file(\*(Aqmy.wsdl\*(Aq): \& \& $definitions\->_accept( $visitor ); .Ve .PP If you need an iterator following the somewhat crude path of dependencies in a \s-1WSDL1.1\s0 definition, you might want to look at SOAP::WSDL::Generator::Iterator::WSDL11. .SH "REFERENCES" .IX Header "REFERENCES" .IP "\(bu" 4 [\s-1GHJV1995\s0] .Sp Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides, (1995): Design Patterns. Elements of Reusable Object-Oriented Software. Addison-Wesley Longman, Amsterdam. .SH "LICENSE AND COPYRIGHT" .IX Header "LICENSE AND COPYRIGHT" Copyright 2004\-2008 Martin Kutter. .PP This file is part of SOAP-WSDL. You may distribute/modify it under the same terms as perl itself .SH "AUTHOR" .IX Header "AUTHOR" Martin Kutter .SH "REPOSITORY INFORMATION" .IX Header "REPOSITORY INFORMATION" .Vb 4 \& $Rev: 391 $ \& $LastChangedBy: kutterma $ \& $Id: Client.pm 391 2007\-11\-17 21:56:13Z kutterma $ \& $HeadURL: https://soap\-wsdl.svn.sourceforge.net/svnroot/soap\-wsdl/SOAP\-WSDL/trunk/lib/SOAP/WSDL/Client.pm $ .Ve