1SOAP::WSDL::Generator::UVsiesritCoorn(t3r)ibuted Perl DoScOuAmPe:n:tWaStDiLo:n:Generator::Visitor(3)
2
3
4
6 SOAP::WSDL::Generator::Visitor - SOAP::WSDL's Visitor-based Code
7 Generator
8
10 SOAP::WSDL features a code generating facility. This code generation
11 facility (in fact there are several of them) is implemented as Visitor
12 to SOAP::WSDL::Base-derived objects.
13
14 The Visitor Pattern
15 The Visitor design pattern is one of the object oriented design pattern
16 described by [GHJV1995].
17
18 A Visitor is an object implementing some behaviour for a fixed set of
19 classes, whose implementation would otherwise need to be scattered
20 across those classes' implementations.
21
22 Visitors are usually combined with Iterators for traversing either a
23 list or tree of objects.
24
25 A Visitor's methods are called using the so-called double dispatch
26 technique. To allow double dispatching, the Visitor implements one
27 method for every class to be handled, whereas every class implements
28 just one method (commonly named "access"), which does nothing more than
29 calling a method on the reference given, with the self object as
30 parameter.
31
32 If all this sounds strange, maybe an example helps. Imagine you had a
33 list of person objects and wanted to print out a list of their names
34 (or address stamps or everything else you like). This can easily be
35 implemented with a Visitor:
36
37 package PersonVisitor;
38 use Class::Std; # handles all basic stuff like constructors etc.
39
40 sub visit_Person {
41 my ( $self, $object ) = @_;
42 print "Person name is ", $object->get_name(), "\n";
43 }
44
45 package Person;
46 use Class::Std;
47 my %name : ATTR(:name<name> :default<anonymous>);
48
49 sub accept { $_[1]->visit_Person( $_[0] ) }
50
51 package main;
52 my @person_from = ();
53 for (qw(Gamma Helm Johnson Vlissides)) {
54 push @person_from, Person->new( { name => $_ } );
55 }
56
57 my $visitor = PersonVisitor->new();
58 for (@person_from) {
59 $_->accept($visitor);
60 }
61
62 # will print
63 Person name is Gamma
64 Person name is Helm
65 Person name is Johnson
66 Person name is Vlissides
67
68 While using this pattern for just printing a list may look a bit over-
69 sized, it may become handy if you need multiple output formats and
70 different classes to operate on.
71
72 The main benefits using visitors are:
73
74 • Grouping related behaviour in one class
75
76 Related behaviour for several classes can be grouped together in
77 the Visitor class. The behaviour can easily be changed by changing
78 the code in one class, instead of having to change all the visited
79 classes.
80
81 • Cleaning up the data classes' implementations
82
83 If classes holding data also implement several different output
84 formats or other (otherwise unrelated) behaviour, they tend to get
85 bloated.
86
87 • Adding behaviour is easy
88
89 Swapping out the visitor class allows easy alterations of
90 behaviour. So on a list of Persons, one Visitor may print address
91 stamps, while another one prints out a phone number list.
92
93 Of course, there are also drawbacks in the visitor pattern:
94
95 • Changes in the visited classes are expensive
96
97 If one of the visited classes changes (or is added), all visitors
98 must be updated to reflect this change. This may be rather
99 expensive if classes change often.
100
101 • The visited classes must expose all data required
102
103 Visitors may need to use the internals of a class. This may result
104 in fidelling with a object's internals, or a bloated interface in
105 the visited class.
106
107 Visitors are usually accompanied by a Iterator. The Iterator may be
108 implemented in the visited classes, in the Visitor, or somewhere else
109 (in the example it was somewhere else).
110
111 The Iterator decides which object to visit next.
112
113 Why SOAP::WSDL uses the Visitor pattern for Code Generation
114 Code generation in SOAP::WSDL means generating various artefacts:
115
116 • Typemaps
117
118 For every WSDL definition, a Typemap is created. The Typemap is
119 used later as an aid in parsing the SOAP XML messages.
120
121 • Type Classes
122
123 For every type defined in the WSDL's schema, a Type Class is
124 generated.
125
126 These classes are instantiated later as a result of parsing SOAP
127 XML messages.
128
129 • Interface Classes
130
131 For every service, a interface class is generated. This class is
132 later used by programmers accessing the service
133
134 • Documentation
135
136 Both Type Classes and Interface Classes include documentation.
137 Additional documentation may be generated as a hint for
138 programmers, or later for mimicking .NET's .asmx example pages.
139
140 All these behaviours could well be (and have historically been)
141 implemented in the classes holding the WSDL data. This made these
142 classes rather bloated, and made it hard to change behaviour (like
143 supporting SOAP Headers, supporting atomic types, and other features
144 which were missing from early versions of SOAP::WSDL).
145
146 Implementing these behaviours in Visitor classes eases adding new
147 behaviours, and reducing the incompletenesses still inherent in
148 SOAP::WSDL's WSDL and XML schema implementation.
149
150 Implementation
151 accept
152
153 SOAP::WSDL::Base defines an accept method which expects a Visitor as
154 only parameter.
155
156 The method visit_Foo_Bar is called on the visitor, with the self object
157 as parameter.
158
159 The actual method name is constructed this way:
160
161 • SOAP::WSDL is stripped from the class name
162
163 • All remaining :: s are replaced by _
164
165 Example:
166
167 When visiting a SOAP::WSDL::XSD::ComplexType object, the method
168 visit_XSD_ComplexType is called on the visitor.
169
170 Writing your own visitor
171 SOAP::WSDL eases writing your own visitor. This might be required if
172 you need some special output format from a WSDL file or want to feed
173 your own serializer/deserializer pair with custom configuration data.
174 Or maybe you want to generate C# code from it...
175
176 To write your own code generating visitor, you should subclass
177 SOAP::WSDL::Generator::Visitor. It implements (empty) default methods
178 for all SOAP::WSDL data classes:
179
180 • visit_Definitions
181
182 • visit_Binding
183
184 • visit_Message
185
186 • visit_Operation
187
188 • visit_OpMessage
189
190 • visit_Part
191
192 • visit_Port
193
194 • visit_PortType
195
196 • visit_Service
197
198 • visit_SoapOperation
199
200 • visit_Types
201
202 • visit_XSD_Schema
203
204 • visit_XSD_ComplexType
205
206 • visit_XSD_Element
207
208 • visit_XSD_SimpleType
209
210 In your Visitor, you must implement visit_Foo methods for all classes
211 you wish to visit.
212
213 The SOAP::WSDL::Generator::Visitor implementations include part of
214 their own Iterator (which means they know how to find the next objects
215 to visit). You may or may not choose to implement a separate Iterator.
216
217 Letting a visitor implementing its own Iterator visit a WSDL definition
218 is as easy as writing something like this:
219
220 my $visitor = MyVisitor->new();
221 my $parser = SOAP::WSDL::Expat::WSDLParser->new();
222 my $definitions = $parser->parse_file('my.wsdl'):
223
224 $definitions->_accept( $visitor );
225
226 If you need an iterator following the somewhat crude path of
227 dependencies in a WSDL1.1 definition, you might want to look at
228 SOAP::WSDL::Generator::Iterator::WSDL11.
229
231 • [GHJV1995]
232
233 Erich Gamma, Richard Helm, Ralph E. Johnson, John Vlissides,
234 (1995): Design Patterns. Elements of Reusable Object-Oriented
235 Software. Addison-Wesley Longman, Amsterdam.
236
238 Copyright 2004-2008 Martin Kutter.
239
240 This file is part of SOAP-WSDL. You may distribute/modify it under the
241 same terms as perl itself
242
244 Martin Kutter <martin.kutter fen-net.de>
245
247 $Rev: 391 $
248 $LastChangedBy: kutterma $
249 $Id: Client.pm 391 2007-11-17 21:56:13Z kutterma $
250 $HeadURL: https://soap-wsdl.svn.sourceforge.net/svnroot/soap-wsdl/SOAP-WSDL/trunk/lib/SOAP/WSDL/Client.pm $
251
252
253
254perl v5.34.0 2021-07-22 SOAP::WSDL::Generator::Visitor(3)