1############################################################################
2# Monte M. Goode, LBNL
3# See LBNLCopyright for copyright notice!
4###########################################################################
5
6# contains text container classes for new generation generator
7
8# $Id: containers.py 1420 2007-10-31 19:51:00Z boverhof $
9import types, warnings
10from utility import StringWriter, TextProtect, TextProtectAttributeName,\
11    GetPartsSubNames
12from utility import NamespaceAliasDict as NAD, NCName_to_ClassName as NC_to_CN
13
14import ZSI
15from ZSI.TC import _is_xsd_or_soap_ns
16from ZSI.wstools import XMLSchema, WSDLTools
17from ZSI.wstools.Namespaces import SCHEMA, SOAP, WSDL
18from ZSI.wstools.logging import getLogger as _GetLogger
19from ZSI.typeinterpreter import BaseTypeInterpreter
20from ZSI.generate import WSISpec, WSInteropError, Wsdl2PythonError,\
21    WsdlGeneratorError, WSDLFormatError
22
23ID1 = '    '
24ID2 = 2*ID1
25ID3 = 3*ID1
26ID4 = 4*ID1
27ID5 = 5*ID1
28ID6 = 6*ID1
29
30KW = {'ID1':ID1, 'ID2':ID2, 'ID3':ID3,'ID4':ID4, 'ID5':ID5, 'ID6':ID6,}
31
32DEC = '_Dec'
33DEF = '_Def'
34
35"""
36type_class_name -- function to return the name formatted as a type class.
37element_class_name -- function to return the name formatted as an element class.
38"""
39type_class_name = lambda n: '%s%s' %(NC_to_CN(n), DEF)
40element_class_name = lambda n: '%s%s' %(NC_to_CN(n), DEC)
41
42
43def IsRPC(item):
44    """item -- OperationBinding instance.
45    """
46    if not isinstance(item, WSDLTools.OperationBinding):
47        raise TypeError, 'IsRPC takes 1 argument of type WSDLTools.OperationBinding'
48    soapbinding = item.getBinding().findBinding(WSDLTools.SoapBinding)
49    sob = item.findBinding(WSDLTools.SoapOperationBinding)
50    style = soapbinding.style
51    if sob is not None:
52        style = sob.style or soapbinding.style
53    return style == 'rpc'
54
55
56def IsLiteral(item):
57    """item -- MessageRoleBinding instance.
58    """
59    if not isinstance(item, WSDLTools.MessageRoleBinding):
60        raise TypeError, 'IsLiteral takes 1 argument of type WSDLTools.MessageRoleBinding'
61    sbb = None
62    if item.type == 'input' or item.type == 'output':
63        sbb = item.findBinding(WSDLTools.SoapBodyBinding)
64    if sbb is None:
65        raise ValueError, 'Missing soap:body binding.'
66    return sbb.use == 'literal'
67
68
69def SetTypeNameFunc(func):
70    global type_class_name
71    type_class_name = func
72
73def SetElementNameFunc(func):
74    global element_class_name
75    element_class_name = func
76
77def GetClassNameFromSchemaItem(item,do_extended=False):
78    '''
79    '''
80    assert isinstance(item, XMLSchema.XMLSchemaComponent), 'must be a schema item.'
81    alias = NAD.getAlias(item.getTargetNamespace())
82    if item.isDefinition() is True:
83        return '%s.%s' %(alias, NC_to_CN('%s' %type_class_name(item.getAttributeName())))
84    return None
85
86def FromMessageGetSimpleElementDeclaration(message):
87    '''If message consists of one part with an element attribute,
88    and this element is a simpleType return a string representing
89    the python type, else return None.
90
91    '''
92    assert isinstance(message, WSDLTools.Message), 'expecting WSDLTools.Message'
93
94    if len(message.parts) == 1 and message.parts[0].element is not None:
95       part = message.parts[0]
96       nsuri,name = part.element
97       wsdl = message.getWSDL()
98       types = wsdl.types
99       if types.has_key(nsuri) and types[nsuri].elements.has_key(name):
100            e = types[nsuri].elements[name]
101            if isinstance(e, XMLSchema.ElementDeclaration) is True and e.getAttribute('type'):
102                typ = e.getAttribute('type')
103                bt = BaseTypeInterpreter()
104                ptype = bt.get_pythontype(typ[1], typ[0])
105                return ptype
106
107    return None
108
109
110class AttributeMixIn:
111    '''for containers that can declare attributes.
112    Class Attributes:
113        attribute_typecode -- typecode attribute name typecode dict
114        built_in_refs -- attribute references that point to built-in
115            types.  Skip resolving them into attribute declarations.
116    '''
117    attribute_typecode = 'self.attribute_typecode_dict'
118    built_in_refs = [(SOAP.ENC, 'arrayType'),]
119
120    def _setAttributes(self, attributes):
121        '''parameters
122        attributes -- a flat list of all attributes,
123        from this list all items in attribute_typecode_dict will
124        be generated into attrComponents.
125
126        returns a list of strings representing the attribute_typecode_dict.
127        '''
128        atd = self.attribute_typecode
129        atd_list = formatted_attribute_list = []
130        if not attributes:
131            return formatted_attribute_list
132
133        atd_list.append('# attribute handling code')
134        idx = 0
135        while(idx < len(attributes)):
136            a = attributes[idx]
137            idx += 1
138            if a.isWildCard() and a.isDeclaration():
139                atd_list.append(\
140                    '%s[("%s","anyAttribute")] = ZSI.TC.AnyElement()'\
141                    % (atd, SCHEMA.XSD3)
142                    )
143            elif a.isDeclaration():
144                tdef = a.getTypeDefinition('type')
145                if tdef is not None:
146                    tc = '%s.%s(None)' %(NAD.getAlias(tdef.getTargetNamespace()),
147                        self.mangle(type_class_name(tdef.getAttributeName()))
148                        )
149                else:
150                    # built-in
151                    t = a.getAttribute('type')
152                    try:
153                        tc = BTI.get_typeclass(t[1], t[0])
154                    except:
155                        # hand back a string by default.
156                        tc = ZSI.TC.String
157
158                    if tc is not None:
159                        tc = '%s()' %tc
160
161                key = None
162                if a.getAttribute('form') == 'qualified':
163                    key = '("%s","%s")' % ( a.getTargetNamespace(),
164                                            a.getAttribute('name') )
165                elif a.getAttribute('form') == 'unqualified':
166                    key = '"%s"' % a.getAttribute('name')
167                else:
168                    raise ContainerError, \
169                          'attribute form must be un/qualified %s' \
170                          % a.getAttribute('form')
171
172                atd_list.append(\
173                    '%s[%s] = %s' % (atd, key, tc)
174                    )
175            elif a.isReference() and a.isAttributeGroup():
176                # flatten 'em out....
177                for ga in a.getAttributeGroup().getAttributeContent():
178                    attributes += (ga,)
179
180            elif a.isReference():
181                try:
182                    ga = a.getAttributeDeclaration()
183                except XMLSchema.SchemaError:
184                    key = a.getAttribute('ref')
185                    self.logger.debug('No schema item for attribute ref (%s, %s)' %key)
186                    if key in self.built_in_refs: continue
187                    raise
188
189                tp = None
190                if ga is not None:
191                    tp = ga.getTypeDefinition('type')
192                    key = '("%s","%s")' %(ga.getTargetNamespace(),
193                             ga.getAttribute('name'))
194
195                if ga is None:
196                    # TODO: probably SOAPENC:arrayType
197                    key = '("%s","%s")' %(
198                             a.getAttribute('ref').getTargetNamespace(),
199                             a.getAttribute('ref').getName())
200                    atd_list.append(\
201                        '%s[%s] = ZSI.TC.String()' %(atd, key)
202                        )
203                elif tp is None:
204                    # built in simple type
205                    try:
206                        namespace,typeName = ga.getAttribute('type')
207                    except TypeError, ex:
208                        # TODO: attribute declaration could be anonymous type
209                        # hack in something to work
210                        atd_list.append(\
211                            '%s[%s] = ZSI.TC.String()' %(atd, key)
212                            )
213                    else:
214                        atd_list.append(\
215                            '%s[%s] = %s()' %(atd, key,
216                                 BTI.get_typeclass(typeName, namespace))
217                            )
218                else:
219                    typeName = tp.getAttribute('name')
220                    namespace = tp.getTargetNamespace()
221                    alias = NAD.getAlias(namespace)
222                    key = '("%s","%s")' \
223                          % (ga.getTargetNamespace(),ga.getAttribute('name'))
224                    atd_list.append(\
225                        '%s[%s] = %s.%s(None)' \
226                        % (atd, key, alias, type_class_name(typeName))
227                        )
228            else:
229                raise TypeError, 'expecting an attribute: %s' %a.getItemTrace()
230
231        return formatted_attribute_list
232
233
234class ContainerError(Exception):
235    pass
236
237
238class ContainerBase:
239    '''Base class for all Containers.
240        func_aname -- function that takes name, and returns aname.
241    '''
242    func_aname = staticmethod(TextProtectAttributeName)
243    logger = _GetLogger("ContainerBase")
244
245    def __init__(self):
246        self.content = StringWriter('\n')
247        self.__setup   = False
248        self.ns    = None
249
250    def __str__(self):
251        return self.getvalue()
252
253    # - string content methods
254    def mangle(self, s):
255        '''class/variable name illegalities
256        '''
257        return TextProtect(s)
258
259    def write(self, s):
260        self.content.write(s)
261
262    def writeArray(self, a):
263        self.content.write('\n'.join(a))
264
265    def _setContent(self):
266        '''override in subclasses.  formats the content in the desired way.
267        '''
268        raise NotImplementedError, 'abstract method not implemented'
269
270    def getvalue(self):
271        if not self.__setup:
272            self._setContent()
273            self.__setup = True
274
275        return self.content.getvalue()
276
277    # - namespace utility methods
278    def getNSAlias(self):
279        if self.ns is not None:
280            return NAD.getAlias(self.ns)
281        raise ContainerError, 'no self.ns attr defined in %s' % self.__class__
282
283    def getNSModuleName(self):
284        if self.ns:
285            return NAD.getModuleName(self.ns)
286        raise ContainerError, 'no self.ns attr defined in %s' % self.__class__
287
288    def getAttributeName(self, name):
289        '''represents the aname
290        '''
291        if self.func_aname is None:
292            return name
293        assert callable(self.func_aname), \
294            'expecting callable method for attribute func_aname, not %s' %type(self.func_aname)
295        f = self.func_aname
296        return f(name)
297
298
299# -- containers for services file components
300
301class ServiceContainerBase(ContainerBase):
302    clientClassSuffix = "SOAP"
303    logger = _GetLogger("ServiceContainerBase")
304
305
306class ServiceHeaderContainer(ServiceContainerBase):
307    imports = ['\nimport urlparse, types',
308              'from ZSI.TCcompound import ComplexType, Struct',
309              'from ZSI import client',
310              'from ZSI.schema import GED, GTD',
311              'import ZSI'
312              ]
313    logger = _GetLogger("ServiceHeaderContainer")
314
315    def __init__(self, do_extended=False):
316        ServiceContainerBase.__init__(self)
317
318        self.basic = self.imports[:]
319        self.types = None
320        self.messages = None
321        self.extras = []
322        self.do_extended = do_extended
323
324    def setTypesModuleName(self, module):
325        self.types = module
326
327    def setMessagesModuleName(self, module):
328        self.messages = module
329
330    def appendImport(self, statement):
331        '''append additional import statement(s).
332        import_stament -- tuple or list or str
333        '''
334        if type(statement) in (list,tuple):
335            self.extras += statement
336        else:
337            self.extras.append(statement)
338
339    def _setContent(self):
340        if self.messages:
341            self.write('from %s import *' % self.messages)
342        if self.types:
343            self.write('from %s import *' % self.types)
344
345        imports = self.basic[:]
346        imports += self.extras
347        self.writeArray(imports)
348
349
350class ServiceLocatorContainer(ServiceContainerBase):
351    logger = _GetLogger("ServiceLocatorContainer")
352
353    def __init__(self):
354        ServiceContainerBase.__init__(self)
355        self.serviceName = None
356        self.portInfo = []
357        self.locatorName = None
358        self.portMethods = []
359
360    def setUp(self, service):
361        assert isinstance(service, WSDLTools.Service), \
362           'expecting WDSLTools.Service instance.'
363
364        self.serviceName = service.name
365        for p in service.ports:
366            try:
367                ab = p.getAddressBinding()
368            except WSDLTools.WSDLError, ex:
369                self.logger.warning('Skip port(%s), missing address binding' %p.name)
370                continue
371            if isinstance(ab, WSDLTools.SoapAddressBinding) is False:
372                self.logger.warning('Skip port(%s), not a SOAP-1.1 address binding' %p.name)
373                continue
374
375            #info = (p.getBinding().getPortType().name, p.getBinding().name, ab.location)
376            self.portInfo.append( (NC_to_CN(p.name),
377                 NC_to_CN(p.getBinding().name),
378                 ab.location)
379            )
380
381    def getLocatorName(self):
382        '''return class name of generated locator.
383        '''
384        return self.locatorName
385
386    def getPortMethods(self):
387        '''list of get port accessor methods of generated locator class.
388        '''
389        return self.portMethods
390
391    def _setContent(self):
392        if not self.serviceName:
393            raise ContainerError, 'no service name defined!'
394
395        self.serviceName = self.mangle(self.serviceName)
396        self.locatorName = '%sLocator' %self.serviceName
397        locator = ['# Locator', 'class %s:' %self.locatorName, ]
398        self.portMethods = []
399        kwargs = KW.copy()
400        for port,bind,addr in self.portInfo:
401            # access method each port
402            method = 'get%s' %port
403            kwargs.update(dict(port=port, bind=bind, addr=addr,
404                service=self.serviceName, suffix=self.clientClassSuffix, method=method))
405
406            locator += [
407                '%(ID1)s%(port)s_address = "%(addr)s"' %kwargs,
408                '%(ID1)sdef get%(port)sAddress(self):' %kwargs,
409                '%(ID2)sreturn %(service)sLocator.%(port)s_address' %kwargs,
410                '%(ID1)sdef %(method)s(self, url=None, **kw):' %kwargs,
411                '%(ID2)sreturn %(bind)s%(suffix)s(url or %(service)sLocator.%(port)s_address, **kw)' %kwargs,
412                ]
413
414            self.portMethods.append(method)
415
416        self.writeArray(locator)
417
418
419class ServiceOperationContainer(ServiceContainerBase):
420    logger = _GetLogger("ServiceOperationContainer")
421
422    def __init__(self, useWSA=False, do_extended=False):
423        '''Parameters:
424              useWSA -- boolean, enable ws-addressing
425              do_extended -- boolean
426        '''
427        ServiceContainerBase.__init__(self)
428        self.useWSA  = useWSA
429        self.do_extended = do_extended
430
431    def hasInput(self):
432        return self.inputName is not None
433
434    def hasOutput(self):
435        return self.outputName is not None
436
437    def isRPC(self):
438        return IsRPC(self.binding_operation)
439
440    def isLiteral(self, input=True):
441        msgrole = self.binding_operation.input
442        if input is False:
443            msgrole = self.binding_operation.output
444        return IsLiteral(msgrole)
445
446    def isSimpleType(self, input=True):
447        if input is False:
448            return self.outputSimpleType
449        return self.inputSimpleType
450
451    def getOperation(self):
452        return self.port.operations.get(self.name)
453
454    def getBOperation(self):
455        return self.port.get(self.name)
456
457    def getOperationName(self):
458        return self.name
459
460    def setUp(self, item):
461        '''
462        Parameters:
463            item -- WSDLTools BindingOperation instance.
464        '''
465        if not isinstance(item, WSDLTools.OperationBinding):
466            raise TypeError, 'Expecting WSDLTools Operation instance'
467
468        if not item.input:
469            raise WSDLFormatError('No <input/> in <binding name="%s"><operation name="%s">' %(
470                item.getBinding().name, item.name))
471
472        self.name = None
473        self.port = None
474        self.soapaction = None
475        self.inputName  = None
476        self.outputName = None
477        self.inputSimpleType  = None
478        self.outputSimpleType = None
479        self.inputAction  = None
480        self.outputAction = None
481        self.port = port = item.getBinding().getPortType()
482        self._wsdl = item.getWSDL()
483        self.name = name = item.name
484        self.binding_operation = bop = item
485
486        self.soap_input_headers = None
487        self.soap_output_headers = None
488
489        op = port.operations.get(name)
490        if op is None:
491            raise WSDLFormatError(
492                '<portType name="%s"/> no match for <binding name="%s"><operation name="%s">' %(
493                port.name, item.getBinding().name, item.name))
494
495        soap_bop = bop.findBinding(WSDLTools.SoapOperationBinding)
496        if soap_bop is None:
497            raise SOAPBindingError, 'expecting SOAP Bindings'
498
499        self.soapaction = soap_bop.soapAction
500        sbody = bop.input.findBinding(WSDLTools.SoapBodyBinding)
501        if not sbody:
502            raise SOAPBindingError('Missing <binding name="%s"><operation name="%s"><input><soap:body>' %(
503                port.binding.name, bop.name))
504
505        self.encodingStyle = None
506        if sbody.use == 'encoded':
507            assert sbody.encodingStyle == SOAP.ENC,\
508                'Supporting encodingStyle=%s, not %s'%(SOAP.ENC, sbody.encodingStyle)
509            self.encodingStyle = sbody.encodingStyle
510
511        self.inputName  = op.getInputMessage().name
512        self.inputSimpleType = \
513            FromMessageGetSimpleElementDeclaration(op.getInputMessage())
514        self.inputAction = op.getInputAction()
515        self.soap_input_headers = bop.input.findBindings(WSDLTools.SoapHeaderBinding)
516
517        if bop.output is not None:
518            sbody = bop.output.findBinding(WSDLTools.SoapBodyBinding)
519            if not item.output:
520                raise WSDLFormatError, "Operation %s, no match for output binding"  %name
521
522            self.outputName = op.getOutputMessage().name
523            self.outputSimpleType = \
524                FromMessageGetSimpleElementDeclaration(op.getOutputMessage())
525            self.outputAction = op.getOutputAction()
526            self.soap_output_headers = bop.output.findBindings(WSDLTools.SoapHeaderBinding)
527
528    def _setContent(self):
529        '''create string representation of operation.
530        '''
531        kwstring = 'kw = {}'
532        tCheck = 'if isinstance(request, %s) is False:' % self.inputName
533        bindArgs = ''
534        if self.encodingStyle is not None:
535            bindArgs = 'encodingStyle="%s", ' %self.encodingStyle
536
537        if self.useWSA:
538            wsactionIn = 'wsaction = "%s"' % self.inputAction
539            wsactionOut = 'wsaction = "%s"' % self.outputAction
540            bindArgs += 'wsaction=wsaction, endPointReference=self.endPointReference, '
541            responseArgs = ', wsaction=wsaction'
542        else:
543            wsactionIn = '# no input wsaction'
544            wsactionOut = '# no output wsaction'
545            responseArgs = ''
546
547        bindArgs += '**kw)'
548
549        if self.do_extended:
550            inputName = self.getOperation().getInputMessage().name
551            wrap_str = ""
552            partsList = self.getOperation().getInputMessage().parts.values()
553            try:
554                subNames = GetPartsSubNames(partsList, self._wsdl)
555            except TypeError, ex:
556                raise Wsdl2PythonError,\
557                    "Extended generation failure: only supports doc/lit, "\
558                    +"and all element attributes (<message><part element="\
559                    +"\"my:GED\"></message>) must refer to single global "\
560                    +"element declaration with complexType content.  "\
561                    +"\n\n**** TRY WITHOUT EXTENDED ****\n"
562
563            args = []
564            for pa in subNames:
565                args += pa
566
567            for arg in args:
568                wrap_str += "%srequest.%s = %s\n" % (ID2,
569                                                     self.getAttributeName(arg),
570                                                     self.mangle(arg))
571
572            #args = [pa.name for pa in self.getOperation().getInputMessage().parts.values()]
573            argsStr = ",".join(args)
574            if len(argsStr) > 1: # add inital comma if args exist
575                argsStr = ", " + argsStr
576
577            method = [
578                '%s# op: %s' % (ID1, self.getOperation().getInputMessage()),
579                '%sdef %s(self%s):' % (ID1, self.name, argsStr),
580                '\n%srequest = %s()' % (ID2, self.inputName),
581                '%s' % (wrap_str),
582                '%s%s' % (ID2, kwstring),
583                '%s%s' % (ID2, wsactionIn),
584                '%sself.binding.Send(None, None, request, soapaction="%s", %s'\
585                %(ID2, self.soapaction, bindArgs),
586            ]
587        elif self.soap_input_headers:
588            method = [
589                '%s# op: %s' % (ID1, self.name),
590                '%sdef %s(self, request, soapheaders=(), **kw):' % (ID1, self.name),
591                '%s%s' % (ID2, tCheck),
592                '%sraise TypeError, "%%s incorrect request type" %% (%s)' %(ID3, 'request.__class__'),
593                '%s%s' % (ID2, wsactionIn),
594                '%s# TODO: Check soapheaders' % (ID2),
595                '%sself.binding.Send(None, None, request, soapaction="%s", soapheaders=soapheaders, %s'\
596                %(ID2, self.soapaction, bindArgs),
597            ]
598        else:
599            method = [
600                '%s# op: %s' % (ID1, self.name),
601                '%sdef %s(self, request, **kw):' % (ID1, self.name),
602                '%s%s' % (ID2, tCheck),
603                '%sraise TypeError, "%%s incorrect request type" %% (%s)' %(ID3, 'request.__class__'),
604                '%s%s' % (ID2, wsactionIn),
605                '%sself.binding.Send(None, None, request, soapaction="%s", %s'\
606                %(ID2, self.soapaction, bindArgs),
607            ]
608        #
609        # BP 1.0: rpc/literal
610        # WSDL 1.1 Section 3.5 could be interpreted to mean the RPC response
611        # wrapper element must be named identical to the name of the
612        # wsdl:operation.
613        # R2729
614
615        #
616        # SOAP-1.1 Note: rpc/encoded
617        # Each parameter accessor has a name corresponding to the name of the
618        # parameter and type corresponding to the type of the parameter. The name of
619        # the return value accessor is not significant. Likewise, the name of the struct is
620        # not significant. However, a convention is to name it after the method name
621        # with the string "Response" appended.
622        #
623        if not self.outputName:
624            method.append('%s#check for soap, assume soap:fault' %(ID2,))
625            method.append('%sif self.binding.IsSOAP(): self.binding.Receive(None, **kw)' % (ID2,))
626            self.writeArray(method)
627            return
628
629        response = ['%s%s' % (ID2, wsactionOut),]
630        if self.isRPC() and not self.isLiteral():
631            # rpc/encoded Replace wrapper name with None
632            response.append(\
633                '%stypecode = Struct(pname=None, ofwhat=%s.typecode.ofwhat, pyclass=%s.typecode.pyclass)' %(
634                     ID2, self.outputName, self.outputName)
635                )
636            response.append(\
637                '%sresponse = self.binding.Receive(typecode%s)' %(
638                     ID2, responseArgs)
639                )
640        else:
641            response.append(\
642                '%sresponse = self.binding.Receive(%s.typecode%s)' %(
643                     ID2, self.outputName, responseArgs)
644                )
645
646        # only support lit
647        if self.soap_output_headers:
648            sh = '['
649            for shb in self.soap_output_headers:
650                #shb.encodingStyle, shb.use, shb.namespace
651                shb.message
652                shb.part
653                try:
654                    msg = self._wsdl.messages[shb.message]
655                    part = msg.parts[shb.part]
656                    if part.element is not None:
657                        sh += 'GED%s,' %str(part.element)
658                    else:
659                        warnings.warn('skipping soap output header in Message "%s"' %str(msg))
660                except:
661                    raise WSDLFormatError(
662                      'failure processing output header typecodes, ' +
663                      'could not find message "%s" or its part "%s"' %(
664                               shb.message, shb.part)
665                    )
666
667            sh += ']'
668            if len(sh) > 2:
669                response.append(\
670                '%sself.soapheaders = self.binding.ps.ParseHeaderElements(%s)' %(ID2, sh)
671                )
672
673        if self.outputSimpleType:
674            response.append('%sreturn %s(response)' %(ID2, self.outputName))
675        else:
676            if self.do_extended:
677                partsList = self.getOperation().getOutputMessage().parts.values()
678                subNames = GetPartsSubNames(partsList, self._wsdl)
679                args = []
680                for pa in subNames:
681                    args += pa
682
683                for arg in args:
684                    response.append('%s%s = response.%s' % (ID2, self.mangle(arg), self.getAttributeName(arg)) )
685                margs = ",".join(args)
686                response.append("%sreturn %s" % (ID2, margs) )
687            else:
688                response.append('%sreturn response' %ID2)
689        method += response
690
691        self.writeArray(method)
692
693
694class BindingDescription(ServiceContainerBase):
695    '''writes out SOAP Binding class
696
697    class variables:
698        readerclass --
699        writerclass --
700        operationclass -- representation of each operation.
701    '''
702    readerclass = None
703    writerclass = None
704    operationclass = ServiceOperationContainer
705    logger = _GetLogger("BindingDescription")
706
707    def __init__(self, useWSA=False, do_extended=False, wsdl=None):
708        '''Parameters:
709        name -- binding name
710        property -- resource properties
711        useWSA   -- boolean, enable ws-addressing
712        name -- binding name
713        '''
714        ServiceContainerBase.__init__(self)
715        self.useWSA = useWSA
716        self.rProp = None
717        #self.bName = None
718        self.operations = None
719        self.do_extended = do_extended
720        self._wsdl = wsdl # None unless do_extended == True
721
722    def setReaderClass(cls, className):
723        '''specify a reader class name, this must be imported
724        in service module.
725        '''
726        cls.readerclass = className
727    setReaderClass = classmethod(setReaderClass)
728
729    def setWriterClass(cls, className):
730        '''specify a writer class name, this must be imported
731        in service module.
732        '''
733        cls.writerclass = className
734    setWriterClass = classmethod(setWriterClass)
735
736    def setOperationClass(cls, className):
737        '''specify an operation container class name.
738        '''
739        cls.operationclass = className
740    setOperationClass = classmethod(setOperationClass)
741
742    def setUp(self, item):
743        '''This method finds all SOAP Binding Operations, it will skip
744        all bindings that are not SOAP.
745        item -- WSDL.Binding instance
746        '''
747        assert isinstance(item, WSDLTools.Binding), \
748              'expecting WSDLTools Binding instance'
749
750        portType = item.getPortType()
751        self._kwargs = KW.copy()
752        self._kwargs['bind'] = NC_to_CN(item.name)
753        self.operations = []
754        self.rProp = portType.getResourceProperties()
755        soap_binding = item.findBinding(WSDLTools.SoapBinding)
756        if soap_binding is None:
757            raise Wsdl2PythonError,\
758                'Binding(%s) missing WSDLTools.SoapBinding' %item.name
759
760        for bop in item.operations:
761            soap_bop = bop.findBinding(WSDLTools.SoapOperationBinding)
762            if soap_bop is None:
763                self.logger.warning(\
764                    'Skip Binding(%s) operation(%s) no SOAP Binding Operation'\
765                    %(item.name, bop.name),
766                )
767                continue
768
769            #soapAction = soap_bop.soapAction
770            if bop.input is not None:
771                soapBodyBind = bop.input.findBinding(WSDLTools.SoapBodyBinding)
772                if soapBodyBind is None:
773                    self.logger.warning(\
774                        'Skip Binding(%s) operation(%s) Bindings(%s) not supported'\
775                        %(item.name, bop.name, bop.extensions)
776                    )
777                    continue
778
779            op = portType.operations.get(bop.name)
780            if op is None:
781                raise Wsdl2PythonError,\
782                    'no matching portType/Binding operation(%s)' % bop.name
783
784            c = self.operationclass(useWSA=self.useWSA,
785                    do_extended=self.do_extended)
786            c.setUp(bop)
787            self.operations.append(c)
788
789    def _setContent(self):
790        if self.useWSA is True:
791            args = 'endPointReference=None, **kw'
792            epr = 'self.endPointReference = endPointReference'
793        else:
794            args = '**kw'
795            epr      = '# no ws-addressing'
796
797        if self.rProp:
798            rp = 'kw.setdefault("ResourceProperties", ("%s","%s"))'\
799                %(self.rProp[0], self.rProp[1])
800        else:
801            rp = '# no resource properties'
802
803        kwargs = self._kwargs
804        kwargs.update(dict(suffix=self.clientClassSuffix,
805            args=args, epr=epr, rp=rp, readerclass=self.readerclass,
806            writerclass=self.writerclass,))
807
808        methods = [
809            '# Methods',
810            'class %(bind)s%(suffix)s:' %kwargs,
811            '%(ID1)sdef __init__(self, url, %(args)s):' %kwargs,
812            '%(ID2)skw.setdefault("readerclass", %(readerclass)s)' %kwargs,
813            '%(ID2)skw.setdefault("writerclass", %(writerclass)s)' %kwargs,
814            '%(ID2)s%(rp)s' % kwargs,
815            '%(ID2)sself.binding = client.Binding(url=url, **kw)' %kwargs,
816            '%(ID2)s%(epr)s' % kwargs,
817            ]
818
819        for op in self.operations:
820            methods += [ op.getvalue() ]
821
822        self.writeArray(methods)
823
824ServiceOperationsClassContainer = BindingDescription
825
826
827class MessageContainerInterface:
828    logger = _GetLogger("MessageContainerInterface")
829
830    def setUp(self, port, soc, input):
831        '''sets the attribute _simple which represents a
832        primitive type message represents, or None if not primitive.
833
834        soc -- WSDLTools.ServiceOperationContainer instance
835        port -- WSDLTools.Port instance
836        input-- boolean, input messasge or output message of operation.
837        '''
838        raise NotImplementedError, 'Message container must implemented setUp.'
839
840
841class ServiceDocumentLiteralMessageContainer(ServiceContainerBase,
842                                             MessageContainerInterface):
843    logger = _GetLogger("ServiceDocumentLiteralMessageContainer")
844
845    def __init__(self, do_extended=False):
846
847        ServiceContainerBase.__init__(self)
848        self.do_extended=do_extended
849
850    def setUp(self, port, soc, input):
851        content = self.content
852        # TODO: check soapbody for part name
853        simple = self._simple = soc.isSimpleType(soc.getOperationName())
854        name = soc.getOperationName()
855
856        # Document/literal
857        operation = port.getBinding().getPortType().operations.get(name)
858        bop = port.getBinding().operations.get(name)
859        soapBodyBind = None
860        if input is True:
861            soapBodyBind = bop.input.findBinding(WSDLTools.SoapBodyBinding)
862            message = operation.getInputMessage()
863        else:
864            soapBodyBind = bop.output.findBinding(WSDLTools.SoapBodyBinding)
865            message = operation.getOutputMessage()
866
867        # using underlying data structure to avoid phantom problem.
868        # with message.parts.data.values()
869        if len(message.parts) == 0:
870            raise Wsdl2PythonError, 'must specify part for doc/lit msg'
871
872        p = None
873        if soapBodyBind.parts is not None:
874            if len(soapBodyBind.parts) > 1:
875                raise Wsdl2PythonError,\
876                    'not supporting multiple parts in soap body'
877            if len(soapBodyBind.parts) == 0:
878                return
879
880            p = message.parts.get(soapBodyBind.parts[0])
881
882        # XXX: Allow for some slop
883        p = p or message.parts[0]
884
885        if p.type:
886            raise  Wsdl2PythonError, 'no doc/lit suport for <part type>'
887
888        if not p.element:
889            return
890
891        self.ns = p.element[0]
892        content.ns = p.element[0]
893        content.pName = p.element[1]
894        content.mName = message.name
895
896    def _setContent(self):
897        '''create string representation of doc/lit message container.  If
898        message element is simple(primitive), use python type as base class.
899        '''
900        try:
901            simple = self._simple
902        except AttributeError:
903            raise RuntimeError, 'call setUp first'
904
905        # TODO: Hidden contract.  Must set self.ns before getNSAlias...
906        #  File "/usr/local/python/lib/python2.4/site-packages/ZSI/generate/containers.py", line 625, in _setContent
907        #    kw['message'],kw['prefix'],kw['typecode'] = \
908        #  File "/usr/local/python/lib/python2.4/site-packages/ZSI/generate/containers.py", line 128, in getNSAlias
909        #    raise ContainerError, 'no self.ns attr defined in %s' % self.__class__
910        # ZSI.generate.containers.ContainerError: no self.ns attr defined in ZSI.generate.containers.ServiceDocumentLiteralMessageContainer
911        #
912#        self.ns = self.content.ns
913
914
915        kw = KW.copy()
916        kw.update(dict(message=self.content.mName, nsuri=self.content.ns,
917                       name=self.content.pName))
918
919#        kw['message'],kw['prefix'],kw['typecode'] = \
920#            self.content.mName, self.getNSAlias(), element_class_name(self.content.pName)
921#
922        # These messsages are just global element declarations
923#        self.writeArray(['%(message)s = %(prefix)s.%(typecode)s().pyclass' %kw])
924        self.writeArray(['%(message)s = GED("%(nsuri)s", "%(name)s").pyclass' %kw])
925
926class ServiceRPCEncodedMessageContainer(ServiceContainerBase, MessageContainerInterface):
927    logger = _GetLogger("ServiceRPCEncodedMessageContainer")
928
929    def setUp(self, port, soc, input):
930        '''
931        Instance Data:
932           op    -- WSDLTools Operation instance
933           bop   -- WSDLTools BindingOperation instance
934           input -- boolean input/output
935        '''
936        name = soc.getOperationName()
937        bop = port.getBinding().operations.get(name)
938        op = port.getBinding().getPortType().operations.get(name)
939
940        assert op is not None, 'port has no operation %s' %name
941        assert bop is not None, 'port has no binding operation %s' %name
942
943        self.input = input
944        self.op = op
945        self.bop = bop
946
947    def _setContent(self):
948        try:
949            self.op
950        except AttributeError:
951            raise RuntimeError, 'call setUp first'
952
953        pname = self.op.name
954        msgRole = self.op.input
955        msgRoleB = self.bop.input
956        if self.input is False:
957            pname = '%sResponse' %self.op.name
958            msgRole = self.op.output
959            msgRoleB = self.bop.output
960
961        sbody = msgRoleB.findBinding(WSDLTools.SoapBodyBinding)
962        if not sbody or not sbody.namespace:
963            raise WSInteropError, WSISpec.R2717
964
965        assert sbody.use == 'encoded', 'Expecting use=="encoded"'
966        encodingStyle = sbody.encodingStyle
967
968        assert encodingStyle == SOAP.ENC,\
969            'Supporting encodingStyle=%s, not %s' %(SOAP.ENC, encodingStyle)
970
971        namespace = sbody.namespace
972        tcb = MessageTypecodeContainer(\
973                  tuple(msgRole.getMessage().parts.list),
974              )
975        ofwhat = '[%s]' %tcb.getTypecodeList()
976        pyclass = msgRole.getMessage().name
977
978        fdict = KW.copy()
979        fdict['nspname'] = sbody.namespace
980        fdict['pname'] = pname
981        fdict['pyclass'] = None
982        fdict['ofwhat'] = ofwhat
983        fdict['encoded'] = namespace
984
985        #if self.input is False:
986        #    fdict['typecode'] = \
987        #        'Struct(pname=None, ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")'
988        #else:
989        fdict['typecode'] = \
990            'Struct(pname=("%(nspname)s","%(pname)s"), ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")'
991
992        message = ['class %(pyclass)s:',
993                    '%(ID1)sdef __init__(self, **kw):',
994                    '%(ID2)s"""Keyword parameters:',
995                    ]
996
997        idx = len(message)
998        for a,p in zip(tcb.getAttributeNames(), tcb.getParameterNames()):
999            message.insert(idx, '%(ID2)s' + p + ' -- part ' + p)
1000            message.append('%(ID2)sself.' + a + ' =  kw.get("%s")' %p)
1001            idx += 1
1002
1003        message.insert(idx, '%(ID2)s"""')
1004
1005        # TODO: This isn't a TypecodeContainerBase instance but it
1006        #    certaintly generates a pyclass and typecode.
1007        #if self.metaclass is None:
1008        if TypecodeContainerBase.metaclass is None:
1009            fdict['pyclass'] = pyclass
1010            fdict['typecode'] = fdict['typecode'] %fdict
1011            message.append('%(pyclass)s.typecode = %(typecode)s')
1012        else:
1013            # Need typecode to be available when class is constructed.
1014            fdict['typecode'] = fdict['typecode'] %fdict
1015            fdict['pyclass'] = pyclass
1016            fdict['metaclass'] = TypecodeContainerBase.metaclass
1017            message.insert(0, '_%(pyclass)sTypecode = %(typecode)s')
1018            message.insert(2, '%(ID1)stypecode = _%(pyclass)sTypecode')
1019            message.insert(3, '%(ID1)s__metaclass__ = %(metaclass)s')
1020            message.append('%(pyclass)s.typecode.pyclass = %(pyclass)s')
1021
1022        self.writeArray(map(lambda l: l %fdict, message))
1023
1024
1025class ServiceRPCLiteralMessageContainer(ServiceContainerBase, MessageContainerInterface):
1026    logger = _GetLogger("ServiceRPCLiteralMessageContainer")
1027
1028    def setUp(self, port, soc, input):
1029        '''
1030        Instance Data:
1031           op    -- WSDLTools Operation instance
1032           bop   -- WSDLTools BindingOperation instance
1033           input -- boolean input/output
1034        '''
1035        name = soc.getOperationName()
1036        bop = port.getBinding().operations.get(name)
1037        op = port.getBinding().getPortType().operations.get(name)
1038
1039        assert op is not None, 'port has no operation %s' %name
1040        assert bop is not None, 'port has no binding operation %s' %name
1041
1042        self.op = op
1043        self.bop = bop
1044        self.input = input
1045
1046    def _setContent(self):
1047        try:
1048            self.op
1049        except AttributeError:
1050            raise RuntimeError, 'call setUp first'
1051
1052        operation = self.op
1053        input = self.input
1054        pname = operation.name
1055        msgRole = operation.input
1056        msgRoleB = self.bop.input
1057        if input is False:
1058            pname = '%sResponse' %operation.name
1059            msgRole = operation.output
1060            msgRoleB = self.bop.output
1061
1062        sbody = msgRoleB.findBinding(WSDLTools.SoapBodyBinding)
1063        if not sbody or not sbody.namespace:
1064            raise WSInteropError, WSISpec.R2717
1065
1066        namespace = sbody.namespace
1067        tcb = MessageTypecodeContainer(\
1068                  tuple(msgRole.getMessage().parts.list),
1069              )
1070        ofwhat = '[%s]' %tcb.getTypecodeList()
1071        pyclass = msgRole.getMessage().name
1072
1073        fdict = KW.copy()
1074        fdict['nspname'] = sbody.namespace
1075        fdict['pname'] = pname
1076        fdict['pyclass'] = None
1077        fdict['ofwhat'] = ofwhat
1078        fdict['encoded'] = namespace
1079        fdict['typecode'] = \
1080            'Struct(pname=("%(nspname)s","%(pname)s"), ofwhat=%(ofwhat)s, pyclass=%(pyclass)s, encoded="%(encoded)s")'
1081
1082        message = ['class %(pyclass)s:',
1083                    '%(ID1)sdef __init__(self, **kw):',
1084                    '%(ID2)s"""Keyword parameters:',
1085                    ]
1086
1087        idx = len(message)
1088        for a,p in zip(tcb.getAttributeNames(), tcb.getParameterNames()):
1089            message.insert(idx, '%(ID2)s' + p + ' -- part ' + p)
1090            message.append('%(ID2)sself.' + a + ' =  kw.get("%s")' %p)
1091            idx += 1
1092
1093        message.insert(idx, '%(ID2)s"""')
1094
1095        # TODO: This isn't a TypecodeContainerBase instance but it
1096        #    certaintly generates a pyclass and typecode.
1097        #if self.metaclass is None:
1098        if TypecodeContainerBase.metaclass is None:
1099            fdict['pyclass'] = pyclass
1100            fdict['typecode'] = fdict['typecode'] %fdict
1101            message.append('%(pyclass)s.typecode = %(typecode)s')
1102        else:
1103            # Need typecode to be available when class is constructed.
1104            fdict['typecode'] = fdict['typecode'] %fdict
1105            fdict['pyclass'] = pyclass
1106            fdict['metaclass'] = TypecodeContainerBase.metaclass
1107            message.insert(0, '_%(pyclass)sTypecode = %(typecode)s')
1108            message.insert(2, '%(ID1)stypecode = _%(pyclass)sTypecode')
1109            message.insert(3, '%(ID1)s__metaclass__ = %(metaclass)s')
1110            message.append('%(pyclass)s.typecode.pyclass = %(pyclass)s')
1111
1112        self.writeArray(map(lambda l: l %fdict, message))
1113
1114
1115TypesContainerBase = ContainerBase
1116
1117
1118class TypesHeaderContainer(TypesContainerBase):
1119    '''imports for all generated types modules.
1120    '''
1121    imports = [
1122        'import ZSI',
1123        'import ZSI.TCcompound',
1124        'from ZSI.schema import LocalElementDeclaration, ElementDeclaration, TypeDefinition, GTD, GED',
1125    ]
1126    logger = _GetLogger("TypesHeaderContainer")
1127
1128    def _setContent(self):
1129        self.writeArray(TypesHeaderContainer.imports)
1130
1131
1132NamespaceClassContainerBase = TypesContainerBase
1133
1134
1135class NamespaceClassHeaderContainer(NamespaceClassContainerBase):
1136    logger = _GetLogger("NamespaceClassHeaderContainer")
1137
1138    def _setContent(self):
1139
1140        head = [
1141            '#' * 30,
1142            '# targetNamespace',
1143            '# %s' % self.ns,
1144            '#' * 30 + '\n',
1145            'class %s:' % self.getNSAlias(),
1146            '%stargetNamespace = "%s"' % (ID1, self.ns)
1147            ]
1148
1149        self.writeArray(head)
1150
1151class NamespaceClassFooterContainer(NamespaceClassContainerBase):
1152    logger = _GetLogger("NamespaceClassFooterContainer")
1153
1154    def _setContent(self):
1155
1156        foot = [
1157            '# end class %s (tns: %s)' % (self.getNSAlias(), self.ns),
1158            ]
1159
1160        self.writeArray(foot)
1161
1162
1163BTI = BaseTypeInterpreter()
1164class TypecodeContainerBase(TypesContainerBase):
1165    '''Base class for all classes representing anything
1166    with element content.
1167
1168    class variables:
1169        mixed_content_aname -- text content will be placed in this attribute.
1170        attributes_aname -- attributes will be placed in this attribute.
1171        metaclass -- set this attribute to specify a pyclass __metaclass__
1172    '''
1173    mixed_content_aname = 'text'
1174    attributes_aname = 'attrs'
1175    metaclass = None
1176    lazy = False
1177    logger = _GetLogger("TypecodeContainerBase")
1178
1179    def __init__(self, do_extended=False, extPyClasses=None):
1180        TypesContainerBase.__init__(self)
1181        self.name = None
1182
1183        # attrs for model groups and others with elements, tclists, etc...
1184        self.allOptional = False
1185        self.mgContent = None
1186        self.contentFlattened = False
1187        self.elementAttrs = []
1188        self.tcListElements = []
1189        self.tcListSet = False
1190
1191        self.localTypes = []
1192
1193        # used when processing nested anonymous types
1194        self.parentClass = None
1195
1196        # used when processing attribute content
1197        self.mixed = False
1198        self.extraFlags = ''
1199        self.attrComponents = None
1200
1201        # --> EXTENDED
1202        # Used if an external pyclass was specified for this type.
1203        self.do_extended = do_extended
1204        if extPyClasses is None:
1205            self.extPyClasses = {}
1206        else:
1207            self.extPyClasses = extPyClasses
1208        # <--
1209
1210    def getvalue(self):
1211        out = ContainerBase.getvalue(self)
1212        for item in self.localTypes:
1213            content = None
1214            assert True is item.isElement() is item.isLocal(), 'expecting local elements only'
1215
1216            etp = item.content
1217            qName = item.getAttribute('type')
1218            if not qName:
1219                etp = item.content
1220                local = True
1221            else:
1222                etp = item.getTypeDefinition('type')
1223
1224            if etp is None:
1225                if local is True:
1226                    content = ElementLocalComplexTypeContainer(do_extended=self.do_extended)
1227                else:
1228                    content = ElementSimpleTypeContainer()
1229            elif etp.isLocal() is False:
1230                content = ElementGlobalDefContainer()
1231            elif etp.isSimple() is True:
1232                content = ElementLocalSimpleTypeContainer()
1233            elif etp.isComplex():
1234                content = ElementLocalComplexTypeContainer(do_extended=self.do_extended)
1235            else:
1236                raise Wsdl2PythonError, "Unknown element declaration: %s" %item.getItemTrace()
1237
1238            content.setUp(item)
1239
1240            out += '\n\n'
1241            if self.parentClass:
1242                content.parentClass = \
1243                    '%s.%s' %(self.parentClass, self.getClassName())
1244            else:
1245                content.parentClass = '%s.%s' %(self.getNSAlias(), self.getClassName())
1246
1247            for l in content.getvalue().split('\n'):
1248                if l: out += '%s%s\n' % (ID1, l)
1249                else: out += '\n'
1250
1251            out += '\n\n'
1252
1253        return out
1254
1255    def getAttributeName(self, name):
1256        '''represents the aname
1257        '''
1258        if self.func_aname is None:
1259            return name
1260        assert callable(self.func_aname), \
1261            'expecting callable method for attribute func_aname, not %s' %type(self.func_aname)
1262        f = self.func_aname
1263        return f(name)
1264
1265    def getMixedTextAName(self):
1266        '''returns an aname representing mixed text content.
1267        '''
1268        return self.getAttributeName(self.mixed_content_aname)
1269
1270    def getClassName(self):
1271
1272        if not self.name:
1273            raise ContainerError, 'self.name not defined!'
1274        if not hasattr(self.__class__, 'type'):
1275            raise ContainerError, 'container type not defined!'
1276
1277        #suffix = self.__class__.type
1278        if self.__class__.type == DEF:
1279            classname = type_class_name(self.name)
1280        elif self.__class__.type == DEC:
1281            classname = element_class_name(self.name)
1282
1283        return self.mangle( classname )
1284
1285    # --> EXTENDED
1286    def hasExtPyClass(self):
1287        if self.name in self.extPyClasses:
1288            return True
1289        else:
1290            return False
1291    # <--
1292
1293    def getPyClass(self):
1294        '''Name of generated inner class that will be specified as pyclass.
1295        '''
1296        # --> EXTENDED
1297        if self.hasExtPyClass():
1298            classInfo = self.extPyClasses[self.name]
1299            return ".".join(classInfo)
1300        # <--
1301
1302        return 'Holder'
1303
1304    def getPyClassDefinition(self):
1305        '''Return a list containing pyclass definition.
1306        '''
1307        kw = KW.copy()
1308
1309        # --> EXTENDED
1310        if self.hasExtPyClass():
1311            classInfo = self.extPyClasses[self.name]
1312            kw['classInfo'] = classInfo[0]
1313            return ["%(ID3)simport %(classInfo)s" %kw ]
1314        # <--
1315
1316        kw['pyclass'] = self.getPyClass()
1317        definition = []
1318        definition.append('%(ID3)sclass %(pyclass)s:' %kw)
1319        if self.metaclass is not None:
1320            kw['type'] = self.metaclass
1321            definition.append('%(ID4)s__metaclass__ = %(type)s' %kw)
1322        definition.append('%(ID4)stypecode = self' %kw)
1323
1324        #TODO: Remove pyclass holder __init__ -->
1325        definition.append('%(ID4)sdef __init__(self):' %kw)
1326        definition.append('%(ID5)s# pyclass' %kw)
1327
1328        # JRB HACK need to call _setElements via getElements
1329        self._setUpElements()
1330
1331        # JRB HACK need to indent additional one level
1332        for el in self.elementAttrs:
1333            kw['element'] = el
1334            definition.append('%(ID2)s%(element)s' %kw)
1335        definition.append('%(ID5)sreturn' %kw)
1336        # <--
1337
1338        # pyclass descriptive name
1339        if self.name is not None:
1340            kw['name'] = self.name
1341            definition.append(\
1342                '%(ID3)s%(pyclass)s.__name__ = "%(name)s_Holder"' %kw
1343                )
1344
1345        return definition
1346
1347    def nsuriLogic(self):
1348        '''set a variable "ns" that represents the targetNamespace in
1349        which this item is defined.  Used for namespacing local elements.
1350        '''
1351        if self.parentClass:
1352            return 'ns = %s.%s.schema' %(self.parentClass, self.getClassName())
1353        return 'ns = %s.%s.schema' %(self.getNSAlias(), self.getClassName())
1354
1355    def schemaTag(self):
1356        if self.ns is not None:
1357            return 'schema = "%s"' % self.ns
1358        raise ContainerError, 'failed to set schema targetNamespace(%s)' %(self.__class__)
1359
1360    def typeTag(self):
1361        if self.name is not None:
1362            return 'type = (schema, "%s")' % self.name
1363        raise ContainerError, 'failed to set type name(%s)' %(self.__class__)
1364
1365    def literalTag(self):
1366        if self.name is not None:
1367            return 'literal = "%s"' % self.name
1368        raise ContainerError, 'failed to set element name(%s)' %(self.__class__)
1369
1370    def getExtraFlags(self):
1371        if self.mixed:
1372            self.extraFlags += 'mixed=True, mixed_aname="%s", ' %self.getMixedTextAName()
1373
1374        return self.extraFlags
1375
1376    def simpleConstructor(self, superclass=None):
1377
1378        if superclass:
1379            return '%s.__init__(self, **kw)' % superclass
1380        else:
1381            return 'def __init__(self, **kw):'
1382
1383    def pnameConstructor(self, superclass=None):
1384
1385        if superclass:
1386            return '%s.__init__(self, pname, **kw)' % superclass
1387        else:
1388            return 'def __init__(self, pname, **kw):'
1389
1390
1391    def _setUpElements(self):
1392        """TODO: Remove this method
1393
1394        This method ONLY sets up the instance attributes.
1395        Dependency instance attribute:
1396            mgContent -- expected to be either a complex definition
1397                with model group content, a model group, or model group
1398                content.  TODO: should only support the first two.
1399        """
1400        self.logger.debug("_setUpElements: %s" %self._item.getItemTrace())
1401        if hasattr(self, '_done'):
1402            #return '\n'.join(self.elementAttrs)
1403            return
1404
1405        self._done = True
1406        flat = []
1407        content = self.mgContent
1408        if type(self.mgContent) is not tuple:
1409            mg = self.mgContent
1410            if not mg.isModelGroup():
1411                mg = mg.content
1412
1413            content = mg.content
1414            if mg.isAll():
1415                flat = content
1416                content = []
1417            elif mg.isModelGroup() and mg.isDefinition():
1418                mg = mg.content
1419                content = mg.content
1420
1421        idx = 0
1422        content = list(content)
1423        while idx < len(content):
1424            c = orig = content[idx]
1425            if c.isElement():
1426                flat.append(c)
1427                idx += 1
1428                continue
1429
1430            if c.isReference() and c.isModelGroup():
1431                c = c.getModelGroupReference()
1432
1433            if c.isDefinition() and c.isModelGroup():
1434                c = c.content
1435
1436            if c.isSequence() or c.isChoice():
1437                begIdx = idx
1438                endIdx = begIdx + len(c.content)
1439                for i in range(begIdx, endIdx):
1440                    content.insert(i, c.content[i-begIdx])
1441
1442                content.remove(orig)
1443                continue
1444
1445            raise ContainerError, 'unexpected schema item: %s' %c.getItemTrace()
1446
1447        for c in flat:
1448            if c.isDeclaration() and c.isElement():
1449                defaultValue = "None"
1450                parent = c
1451                defs = []
1452                # stop recursion via global ModelGroupDefinition
1453                while defs.count(parent) <= 1:
1454                    maxOccurs = parent.getAttribute('maxOccurs')
1455                    if maxOccurs == 'unbounded' or int(maxOccurs) > 1:
1456                        defaultValue = "[]"
1457                        break
1458
1459                    parent = parent._parent()
1460                    if not parent.isModelGroup():
1461                        break
1462
1463                    if parent.isReference():
1464                        parent = parent.getModelGroupReference()
1465
1466                    if parent.isDefinition():
1467                        parent = parent.content
1468                        defs.append(parent)
1469
1470                if None ==  c.getAttribute('name') and c.isWildCard():
1471                    e = '%sself.%s = %s' %(ID3,
1472                            self.getAttributeName('any'), defaultValue)
1473                else:
1474                    e = '%sself.%s = %s' %(ID3,
1475                            self.getAttributeName(c.getAttribute('name')), defaultValue)
1476                self.elementAttrs.append(e)
1477                continue
1478
1479            # TODO: This seems wrong
1480            if c.isReference():
1481                e = '%sself._%s = None' %(ID3,
1482                        self.mangle(c.getAttribute('ref')[1]))
1483                self.elementAttrs.append(e)
1484                continue
1485
1486            raise ContainerError, 'unexpected item: %s' % c.getItemTrace()
1487
1488        #return '\n'.join(self.elementAttrs)
1489        return
1490
1491    def _setTypecodeList(self):
1492        """generates ofwhat content, minOccurs/maxOccurs facet generation.
1493        Dependency instance attribute:
1494            mgContent -- expected to be either a complex definition
1495                with model group content, a model group, or model group
1496                content.  TODO: should only support the first two.
1497            localTypes -- produce local class definitions later
1498            tcListElements -- elements, local/global
1499        """
1500        self.logger.debug("_setTypecodeList(%r): %s" %
1501                          (self.mgContent, self._item.getItemTrace()))
1502
1503        flat = []
1504        content = self.mgContent
1505
1506        #TODO: too much slop permitted here, impossible
1507        # to tell what is going on.
1508
1509        if type(content) is not tuple:
1510            mg = content
1511            if not mg.isModelGroup():
1512                raise Wsdl2PythonErr("Expecting ModelGroup: %s" %
1513                                     mg.getItemTrace())
1514
1515            self.logger.debug("ModelGroup(%r) contents(%r): %s" %
1516                  (mg, mg.content, mg.getItemTrace()))
1517
1518            #<group ref>
1519            if mg.isReference():
1520                raise RuntimeError("Unexpected modelGroup reference: %s" %
1521                                   mg.getItemTrace())
1522
1523            #<group name>
1524            if mg.isDefinition():
1525                mg = mg.content
1526
1527            if mg.isAll():
1528                flat = mg.content
1529                content = []
1530            elif mg.isSequence():
1531                content = mg.content
1532            elif mg.isChoice():
1533                content = mg.content
1534            else:
1535                raise RuntimeError("Unknown schema item")
1536
1537        idx = 0
1538        content = list(content)
1539        self.logger.debug("content: %r" %content)
1540        while idx < len(content):
1541            c = orig = content[idx]
1542            if c.isElement():
1543                flat.append(c)
1544                idx += 1
1545                continue
1546
1547            if c.isReference() and c.isModelGroup():
1548                c = c.getModelGroupReference()
1549
1550            if c.isDefinition() and c.isModelGroup():
1551                c = c.content
1552
1553            if c.isSequence() or c.isChoice():
1554                begIdx = idx
1555                endIdx = begIdx + len(c.content)
1556                for i in range(begIdx, endIdx):
1557                    content.insert(i, c.content[i-begIdx])
1558
1559                content.remove(orig)
1560                continue
1561
1562            raise ContainerError, 'unexpected schema item: %s' %c.getItemTrace()
1563
1564        # TODO: Need to store "parents" in a dict[id] = list(),
1565        #    because cannot follow references, but not currently
1566        #    a big concern.
1567
1568        self.logger.debug("flat: %r" %list(flat))
1569        for c in flat:
1570            tc = TcListComponentContainer()
1571            # TODO: Remove _getOccurs
1572            min,max,nil = self._getOccurs(c)
1573            min = max = None
1574            maxOccurs = 1
1575
1576            parent = c
1577            defs = []
1578            # stop recursion via global ModelGroupDefinition
1579            while defs.count(parent) <= 1:
1580                max = parent.getAttribute('maxOccurs')
1581                if max == 'unbounded':
1582                    maxOccurs = '"%s"' %max
1583                    break
1584
1585                maxOccurs = int(max) * maxOccurs
1586                parent = parent._parent()
1587                if not parent.isModelGroup():
1588                    break
1589
1590                if parent.isReference():
1591                    parent = parent.getModelGroupReference()
1592
1593                if parent.isDefinition():
1594                    parent = parent.content
1595                    defs.append(parent)
1596
1597            del defs
1598            parent = c
1599            while 1:
1600                minOccurs = int(parent.getAttribute('minOccurs'))
1601                if minOccurs == 0 or parent.isChoice():
1602                    minOccurs = 0
1603                    break
1604
1605                parent = parent._parent()
1606                if not parent.isModelGroup():
1607                    minOccurs = int(c.getAttribute('minOccurs'))
1608                    break
1609
1610                if parent.isReference():
1611                    parent = parent.getModelGroupReference()
1612
1613                if parent.isDefinition():
1614                    parent = parent.content
1615
1616            tc.setOccurs(minOccurs, maxOccurs, nil)
1617            processContents = self._getProcessContents(c)
1618            tc.setProcessContents(processContents)
1619            if c.isDeclaration() and c.isElement():
1620                global_type = c.getAttribute('type')
1621                content = getattr(c, 'content', None)
1622                if c.isLocal() and c.isQualified() is False:
1623                    tc.unQualified()
1624
1625                if c.isWildCard():
1626                    tc.setStyleAnyElement()
1627                elif global_type is not None:
1628                    tc.name = c.getAttribute('name')
1629                    ns = global_type[0]
1630                    if ns in SCHEMA.XSD_LIST:
1631                        tpc = BTI.get_typeclass(global_type[1],global_type[0])
1632                        tc.klass = tpc
1633#                    elif (self.ns,self.name) == global_type:
1634#                        # elif self._isRecursiveElement(c)
1635#                        # TODO: Remove this, it only works for 1 level.
1636#                        tc.setStyleRecursion()
1637                    else:
1638                        tc.setGlobalType(*global_type)
1639#                        tc.klass = '%s.%s' % (NAD.getAlias(ns),
1640#                            type_class_name(global_type[1]))
1641                    del ns
1642                elif content is not None and content.isLocal() and content.isComplex():
1643                    tc.name = c.getAttribute('name')
1644                    tc.klass = 'self.__class__.%s' % (element_class_name(tc.name))
1645                    #TODO: Not an element reference, confusing nomenclature
1646                    tc.setStyleElementReference()
1647                    self.localTypes.append(c)
1648                elif content is not None and content.isLocal() and content.isSimple():
1649                    # Local Simple Type
1650                    tc.name = c.getAttribute('name')
1651                    tc.klass = 'self.__class__.%s' % (element_class_name(tc.name))
1652                    #TODO: Not an element reference, confusing nomenclature
1653                    tc.setStyleElementReference()
1654                    self.localTypes.append(c)
1655                else:
1656                    raise ContainerError, 'unexpected item: %s' % c.getItemTrace()
1657
1658            elif c.isReference():
1659                # element references
1660                ref = c.getAttribute('ref')
1661#                tc.klass = '%s.%s' % (NAD.getAlias(ref[0]),
1662#                                          element_class_name(ref[1]) )
1663                tc.setStyleElementReference()
1664                tc.setGlobalType(*ref)
1665            else:
1666                raise ContainerError, 'unexpected item: %s' % c.getItemTrace()
1667
1668            self.tcListElements.append(tc)
1669
1670    def getTypecodeList(self):
1671        if not self.tcListSet:
1672#            self._flattenContent()
1673            self._setTypecodeList()
1674            self.tcListSet = True
1675
1676        list = []
1677        for e in self.tcListElements:
1678            list.append(str(e))
1679
1680        return ', '.join(list)
1681
1682    # the following _methods() are utility methods used during
1683    # TCList generation, et al.
1684
1685    def _getOccurs(self, e):
1686
1687        nillable = e.getAttribute('nillable')
1688        if nillable == 'true':
1689            nillable = True
1690        else:
1691            nillable = False
1692
1693        maxOccurs = e.getAttribute('maxOccurs')
1694        if maxOccurs == 'unbounded':
1695            maxOccurs = '"%s"' %maxOccurs
1696
1697        minOccurs = e.getAttribute('minOccurs')
1698
1699        if self.allOptional is True:
1700            #JRB Hack
1701            minOccurs = '0'
1702            maxOccurs = '"unbounded"'
1703
1704        return minOccurs,maxOccurs,nillable
1705
1706    def _getProcessContents(self, e):
1707        processContents = e.getAttribute('processContents')
1708        return processContents
1709
1710    def getBasesLogic(self, indent):
1711        try:
1712            prefix = NAD.getAlias(self.sKlassNS)
1713        except WsdlGeneratorError, ex:
1714            # XSD or SOAP
1715            raise
1716
1717        bases = []
1718        bases.append(\
1719            'if %s.%s not in %s.%s.__bases__:'\
1720            %(NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass), self.getNSAlias(), self.getClassName()),
1721        )
1722        bases.append(\
1723            '%sbases = list(%s.%s.__bases__)'\
1724            %(ID1,self.getNSAlias(),self.getClassName()),
1725        )
1726        bases.append(\
1727            '%sbases.insert(0, %s.%s)'\
1728            %(ID1,NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass) ),
1729        )
1730        bases.append(\
1731            '%s%s.%s.__bases__ = tuple(bases)'\
1732            %(ID1, self.getNSAlias(), self.getClassName())
1733        )
1734
1735        s = ''
1736        for b in bases:
1737            s += '%s%s\n' % (indent, b)
1738
1739        return s
1740
1741
1742class MessageTypecodeContainer(TypecodeContainerBase):
1743    '''Used for RPC style messages, where we have
1744    serveral parts serialized within a rpc wrapper name.
1745    '''
1746    logger = _GetLogger("MessageTypecodeContainer")
1747
1748    def __init__(self, parts=None):
1749        TypecodeContainerBase.__init__(self)
1750        self.mgContent = parts
1751
1752    def _getOccurs(self, e):
1753        '''return a 3 item tuple
1754        '''
1755        minOccurs = maxOccurs = '1'
1756        nillable = True
1757        return minOccurs,maxOccurs,nillable
1758
1759    def _setTypecodeList(self):
1760        self.logger.debug("_setTypecodeList: %s" %
1761            str(self.mgContent))
1762
1763        assert type(self.mgContent) is tuple,\
1764            'expecting tuple for mgContent not: %s' %type(self.mgContent)
1765
1766        for p in self.mgContent:
1767            # JRB
1768            #   not sure what needs to be set for tc, this should be
1769            #   the job of the constructor or a setUp method.
1770            min,max,nil = self._getOccurs(p)
1771            if p.element:
1772                raise  WSInteropError, WSISpec.R2203
1773            elif p.type:
1774                nsuri,name = p.type
1775                tc = RPCMessageTcListComponentContainer(qualified=False)
1776                tc.setOccurs(min, max, nil)
1777                tc.name = p.name
1778                if nsuri in [SOAP.ENC] + SCHEMA.XSD_LIST:
1779                    tpc = BTI.get_typeclass(name, nsuri)
1780                    tc.klass = tpc
1781                else:
1782                    tc.klass = '%s.%s' % (NAD.getAlias(nsuri), type_class_name(name) )
1783            else:
1784                raise ContainerError, 'part must define an element or type attribute'
1785
1786            self.tcListElements.append(tc)
1787
1788    def getTypecodeList(self):
1789        if not self.tcListSet:
1790            self._setTypecodeList()
1791            self.tcListSet = True
1792
1793        list = []
1794        for e in self.tcListElements:
1795            list.append(str(e))
1796        return ', '.join(list)
1797
1798    def getAttributeNames(self):
1799        '''returns a list of anames representing the parts
1800        of the message.
1801        '''
1802        return map(lambda e: self.getAttributeName(e.name), self.tcListElements)
1803
1804    def getParameterNames(self):
1805        '''returns a list of pnames representing the parts
1806        of the message.
1807        '''
1808        return map(lambda e: e.name, self.tcListElements)
1809
1810    def setParts(self, parts):
1811        self.mgContent = parts
1812
1813
1814class TcListComponentContainer(ContainerBase):
1815    '''Encapsulates a single value in the TClist list.
1816    it inherits TypecodeContainerBase only to get the mangle() method,
1817    it does not call the baseclass ctor.
1818
1819    TODO: Change this inheritance scheme.
1820    '''
1821    logger = _GetLogger("TcListComponentContainer")
1822
1823    def __init__(self, qualified=True):
1824        '''
1825        qualified -- qualify element.  All GEDs should be qualified,
1826            but local element declarations qualified if form attribute
1827            is qualified, else they are unqualified. Only relevant for
1828            standard style.
1829        '''
1830        #TypecodeContainerBase.__init__(self)
1831        ContainerBase.__init__(self)
1832
1833        self.qualified = qualified
1834        self.name = None
1835        self.klass = None
1836        self.global_type = None
1837
1838        self.min = None
1839        self.max = None
1840        self.nil = None
1841        self.style = None
1842        self.setStyleElementDeclaration()
1843
1844    def setOccurs(self, min, max, nil):
1845        self.min = min
1846        self.max = max
1847        self.nil = nil
1848
1849    def setProcessContents(self, processContents):
1850        self.processContents = processContents
1851
1852    def setGlobalType(self, namespace, name):
1853        self.global_type = (namespace, name)
1854
1855    def setStyleElementDeclaration(self):
1856        '''set the element style.
1857            standard -- GED or local element
1858        '''
1859        self.style = 'standard'
1860
1861    def setStyleElementReference(self):
1862        '''set the element style.
1863            ref -- element reference
1864        '''
1865        self.style = 'ref'
1866
1867    def setStyleAnyElement(self):
1868        '''set the element style.
1869            anyElement -- <any> element wildcard
1870        '''
1871        self.name = 'any'
1872        self.style = 'anyElement'
1873
1874#    def setStyleRecursion(self):
1875#        '''TODO: Remove.  good for 1 level
1876#        '''
1877#        self.style = 'recursion'
1878
1879    def unQualified(self):
1880        '''Do not qualify element.
1881        '''
1882        self.qualified = False
1883
1884    def _getOccurs(self):
1885        return 'minOccurs=%s, maxOccurs=%s, nillable=%s' \
1886               % (self.min, self.max, self.nil)
1887
1888    def _getProcessContents(self):
1889        return 'processContents="%s"' \
1890               % (self.processContents)
1891
1892    def _getvalue(self):
1893        kw = {'occurs':self._getOccurs(),
1894              'aname':self.getAttributeName(self.name),
1895              'klass':self.klass,
1896              'lazy':TypecodeContainerBase.lazy,
1897              'typed':'typed=False',
1898              'encoded':'encoded=kw.get("encoded")'}
1899
1900        gt = self.global_type
1901        if gt is not None:
1902            kw['nsuri'],kw['type'] = gt
1903
1904        if self.style == 'standard':
1905            kw['pname'] = '"%s"' %self.name
1906            if self.qualified is True:
1907                kw['pname'] =  '(ns,"%s")' %self.name
1908            if gt is None:
1909                return '%(klass)s(pname=%(pname)s, aname="%(aname)s", %(occurs)s, %(typed)s, %(encoded)s)' %kw
1910            return 'GTD("%(nsuri)s","%(type)s",lazy=%(lazy)s)(pname=%(pname)s, aname="%(aname)s", %(occurs)s, %(typed)s, %(encoded)s)' %kw
1911
1912        if self.style == 'ref':
1913            if gt is None:
1914                return '%(klass)s(%(occurs)s, %(encoded)s)' %kw
1915            return 'GED("%(nsuri)s","%(type)s",lazy=%(lazy)s, isref=True)(%(occurs)s, %(encoded)s)' %kw
1916
1917        kw['process'] = self._getProcessContents()
1918        if self.style == 'anyElement':
1919            return 'ZSI.TC.AnyElement(aname="%(aname)s", %(occurs)s, %(process)s)' %kw
1920
1921#        if self.style == 'recursion':
1922#            return 'ZSI.TC.AnyElement(aname="%(aname)s", %(occurs)s, %(process)s)' %kw
1923
1924        raise RuntimeError, 'Must set style for typecode list generation'
1925
1926    def __str__(self):
1927        return self._getvalue()
1928
1929
1930class RPCMessageTcListComponentContainer(TcListComponentContainer):
1931    '''Container for rpc/literal rpc/encoded message typecode.
1932    '''
1933    logger = _GetLogger("RPCMessageTcListComponentContainer")
1934
1935    def __init__(self, qualified=True, encoded=None):
1936        '''
1937        encoded -- encoded namespaceURI, if None treat as rpc/literal.
1938        '''
1939        TcListComponentContainer.__init__(self, qualified=qualified)
1940        self._encoded = encoded
1941
1942    def _getvalue(self):
1943        encoded = self._encoded
1944        if encoded is not None:
1945            encoded = '"%s"' %self._encoded
1946
1947        if self.style == 'standard':
1948            pname = '"%s"' %self.name
1949            if self.qualified is True:
1950                pname = '(ns,"%s")' %self.name
1951            return '%s(pname=%s, aname="%s", typed=False, encoded=%s, %s)' \
1952                   %(self.klass, pname, self.getAttributeName(self.name),
1953                     encoded, self._getOccurs())
1954        elif self.style == 'ref':
1955            return '%s(encoded=%s, %s)' % (self.klass, encoded, self._getOccurs())
1956        elif self.style == 'anyElement':
1957            return 'ZSI.TC.AnyElement(aname="%s", %s, %s)' \
1958                %(self.getAttributeName(self.name), self._getOccurs(), self._getProcessContents())
1959#        elif self.style == 'recursion':
1960#            return 'ZSI.TC.AnyElement(aname="%s", %s, %s)' \
1961#                % (self.getAttributeName(self.name), self._getOccurs(), self._getProcessContents())
1962
1963        raise RuntimeError('Must set style(%s) for typecode list generation' %
1964                           self.style)
1965
1966
1967class ElementSimpleTypeContainer(TypecodeContainerBase):
1968    type = DEC
1969    logger = _GetLogger("ElementSimpleTypeContainer")
1970
1971    def _substitutionGroupTag(self):
1972        value = self.substitutionGroup
1973        if not value:
1974            return 'substitutionGroup = None'
1975
1976        nsuri,ncname = value
1977        return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname)
1978
1979    def _setContent(self):
1980        aname = self.getAttributeName(self.name)
1981        pyclass = self.pyclass
1982
1983        # bool cannot be subclassed
1984        if pyclass == 'bool': pyclass = 'int'
1985        kw = KW.copy()
1986        kw.update(dict(aname=aname, ns=self.ns, name=self.name,
1987                       substitutionGroup=self._substitutionGroupTag(),
1988                       subclass=self.sKlass,literal=self.literalTag(),
1989                       schema=self.schemaTag(), init=self.simpleConstructor(),
1990                       klass=self.getClassName(), element="ElementDeclaration"))
1991
1992        if self.local:
1993            kw['element'] = 'LocalElementDeclaration'
1994
1995        element = map(lambda i: i %kw, [
1996            '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):',
1997            '%(ID2)s%(literal)s',
1998            '%(ID2)s%(schema)s',
1999            '%(ID2)s%(init)s',
2000            '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")',
2001            '%(ID3)skw["aname"] = "%(aname)s"',
2002            ]
2003        )
2004
2005        # TODO: What about getPyClass and getPyClassDefinition?
2006        #     I want to add pyclass metaclass here but this needs to be
2007        #     corrected first.
2008        #
2009        # anyType (?others) has no pyclass.
2010        app = element.append
2011        if pyclass is not None:
2012            app('%sclass IHolder(%s): typecode=self' % (ID3, pyclass),)
2013            app('%skw["pyclass"] = IHolder' %(ID3),)
2014            app('%sIHolder.__name__ = "%s_immutable_holder"' %(ID3, aname),)
2015
2016        app('%s%s' % (ID3, self.simpleConstructor(self.sKlass)),)
2017
2018        self.writeArray(element)
2019
2020    def setUp(self, tp):
2021        self._item = tp
2022        self.local = tp.isLocal()
2023        try:
2024            self.name = tp.getAttribute('name')
2025            self.substitutionGroup = tp.getAttribute('substitutionGroup')
2026            self.ns = tp.getTargetNamespace()
2027            qName = tp.getAttribute('type')
2028        except Exception, ex:
2029            raise Wsdl2PythonError('Error occured processing element: %s' %(
2030                tp.getItemTrace()), *ex.args)
2031
2032        if qName is None:
2033            raise Wsdl2PythonError('Missing QName for element type attribute: %s' %tp.getItemTrace())
2034
2035        tns,local = qName.getTargetNamespace(),qName.getName()
2036        self.sKlass = BTI.get_typeclass(local, tns)
2037        if self.sKlass is None:
2038            raise Wsdl2PythonError('No built-in typecode for type definition("%s","%s"): %s' %(tns,local,tp.getItemTrace()))
2039
2040        try:
2041            self.pyclass = BTI.get_pythontype(None, None, typeclass=self.sKlass)
2042        except Exception, ex:
2043            raise Wsdl2PythonError('Error occured processing element: %s' %(
2044                tp.getItemTrace()), *ex.args)
2045
2046
2047class ElementLocalSimpleTypeContainer(TypecodeContainerBase):
2048    '''local simpleType container
2049    '''
2050    type = DEC
2051    logger = _GetLogger("ElementLocalSimpleTypeContainer")
2052
2053    def _setContent(self):
2054        kw = KW.copy()
2055        kw.update(dict(aname=self.getAttributeName(self.name), ns=self.ns, name=self.name,
2056                       subclass=self.sKlass,literal=self.literalTag(),
2057                       schema=self.schemaTag(), init=self.simpleConstructor(),
2058                       klass=self.getClassName(), element="ElementDeclaration",
2059                       baseinit=self.simpleConstructor(self.sKlass)))
2060
2061        if self.local:
2062            kw['element'] = 'LocalElementDeclaration'
2063
2064        element = map(lambda i: i %kw, [
2065            '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):',
2066            '%(ID2)s%(literal)s',
2067            '%(ID2)s%(schema)s',
2068            '%(ID2)s%(init)s',
2069            '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")',
2070            '%(ID3)skw["aname"] = "%(aname)s"',
2071            '%(ID3)s%(baseinit)s',
2072            ]
2073        )
2074
2075        app = element.append
2076        pyclass = self.pyclass
2077        if pyclass is not None:
2078            # bool cannot be subclassed
2079            if pyclass == 'bool': pyclass = 'int'
2080            kw['pyclass'] = pyclass
2081            app('%(ID3)sclass IHolder(%(pyclass)s): typecode=self' %kw)
2082            app('%(ID3)sself.pyclass = IHolder' %kw)
2083            app('%(ID3)sIHolder.__name__ = "%(aname)s_immutable_holder"' %kw)
2084
2085        self.writeArray(element)
2086
2087    def _setup_pyclass(self):
2088        try:
2089            self.pyclass = BTI.get_pythontype(None, None,
2090                                              typeclass=self.sKlass)
2091        except Exception, ex:
2092            raise Wsdl2PythonError('Error occured processing element: %s' %(
2093                self._item.getItemTrace()), *ex.args)
2094
2095    def setUp(self, tp):
2096        self._item = tp
2097        assert tp.isElement() is True and tp.content is not None and \
2098            tp.content.isLocal() is True and tp.content.isSimple() is True ,\
2099            'expecting local simple type: %s' %tp.getItemTrace()
2100
2101        self.local = tp.isLocal()
2102        self.name = tp.getAttribute('name')
2103        self.ns = tp.getTargetNamespace()
2104        content = tp.content.content
2105        if content.isRestriction():
2106            try:
2107                 base = content.getTypeDefinition()
2108            except XMLSchema.SchemaError, ex:
2109                 base = None
2110
2111            qName = content.getAttributeBase()
2112            if base is None:
2113                self.sKlass = BTI.get_typeclass(qName[1], qName[0])
2114                self._setup_pyclass()
2115                return
2116
2117            raise Wsdl2PythonError, 'unsupported local simpleType restriction: %s' \
2118                %tp.content.getItemTrace()
2119
2120        if content.isList():
2121            try:
2122                 base = content.getTypeDefinition()
2123            except XMLSchema.SchemaError, ex:
2124                 base = None
2125
2126            if base is None:
2127                qName = content.getItemType()
2128                self.sKlass = BTI.get_typeclass(qName[1], qName[0])
2129                self._setup_pyclass()
2130                return
2131
2132            raise Wsdl2PythonError, 'unsupported local simpleType List: %s' \
2133                %tp.content.getItemTrace()
2134
2135        if content.isUnion():
2136            raise Wsdl2PythonError, 'unsupported local simpleType Union: %s' \
2137                %tp.content.getItemTrace()
2138
2139        raise Wsdl2PythonError, 'unexpected schema item: %s' \
2140            %tp.content.getItemTrace()
2141
2142
2143class ElementLocalComplexTypeContainer(TypecodeContainerBase, AttributeMixIn):
2144    type = DEC
2145    logger = _GetLogger("ElementLocalComplexTypeContainer")
2146
2147    def _setContent(self):
2148        kw = KW.copy()
2149        try:
2150            kw.update(dict(klass=self.getClassName(),
2151                       subclass='ZSI.TCcompound.ComplexType',
2152                       element='ElementDeclaration',
2153                       literal=self.literalTag(),
2154                       schema=self.schemaTag(),
2155                       init=self.simpleConstructor(),
2156                       ns=self.ns, name=self.name,
2157                       aname=self.getAttributeName(self.name),
2158                       nsurilogic=self.nsuriLogic(),
2159                       ofwhat=self.getTypecodeList(),
2160                       atypecode=self.attribute_typecode,
2161                       pyclass=self.getPyClass(),
2162                       ))
2163        except Exception, ex:
2164            args = ['Failure processing an element w/local complexType: %s' %(
2165                          self._item.getItemTrace())]
2166            args += ex.args
2167            ex.args = tuple(args)
2168            raise
2169
2170        if self.local:
2171            kw['element'] = 'LocalElementDeclaration'
2172
2173        element = [
2174            '%(ID1)sclass %(klass)s(%(subclass)s, %(element)s):',
2175            '%(ID2)s%(literal)s',
2176            '%(ID2)s%(schema)s',
2177            '%(ID2)s%(init)s',
2178            '%(ID3)s%(nsurilogic)s',
2179            '%(ID3)sTClist = [%(ofwhat)s]',
2180            '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")',
2181            '%(ID3)skw["aname"] = "%(aname)s"',
2182            '%(ID3)s%(atypecode)s = {}',
2183            '%(ID3)sZSI.TCcompound.ComplexType.__init__(self,None,TClist,inorder=0,**kw)',
2184            ]
2185        for l in self.attrComponents: element.append('%(ID3)s'+str(l))
2186        element += self.getPyClassDefinition()
2187        element.append('%(ID3)sself.pyclass = %(pyclass)s' %kw)
2188        self.writeArray(map(lambda l: l %kw, element))
2189
2190    def setUp(self, tp):
2191        '''
2192        {'xsd':['annotation', 'simpleContent', 'complexContent',\
2193        'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\
2194        'anyAttribute', 'any']}
2195        '''
2196        #
2197        # TODO: Need a Recursive solution, this is incomplete will ignore many
2198        #  extensions, restrictions, etc.
2199        #
2200        self._item = tp
2201        # JRB HACK SUPPORTING element/no content.
2202        assert tp.isElement() is True and \
2203            (tp.content is None or (tp.content.isComplex() is True and tp.content.isLocal() is True)),\
2204            'expecting element w/local complexType not: %s' %tp.content.getItemTrace()
2205
2206        self.name = tp.getAttribute('name')
2207        self.ns = tp.getTargetNamespace()
2208        self.local = tp.isLocal()
2209
2210        complex = tp.content
2211        # JRB HACK SUPPORTING element/no content.
2212        if complex is None:
2213            self.mgContent = ()
2214            return
2215
2216        #attributeContent = complex.getAttributeContent()
2217        #self.mgContent = None
2218        if complex.content is None:
2219            self.mgContent = ()
2220            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2221            return
2222
2223        is_simple = complex.content.isSimple()
2224        if is_simple and complex.content.content.isExtension():
2225            # TODO: Not really supported just passing thru
2226            self.mgContent = ()
2227            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2228            return
2229
2230        if is_simple and complex.content.content.isRestriction():
2231            # TODO: Not really supported just passing thru
2232            self.mgContent = ()
2233            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2234            return
2235
2236        if is_simple:
2237            raise ContainerError, 'not implemented local complexType/simpleContent: %s'\
2238               %tp.getItemTrace()
2239
2240        is_complex = complex.content.isComplex()
2241        if is_complex and complex.content.content is None:
2242            # TODO: Recursion...
2243            self.mgContent = ()
2244            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2245            return
2246
2247        if (is_complex and complex.content.content.isExtension() and
2248            complex.content.content.content is not None and
2249            complex.content.content.content.isModelGroup()):
2250
2251            self.mgContent = complex.content.content.content.content
2252            self.attrComponents = self._setAttributes(
2253                    complex.content.content.getAttributeContent()
2254                )
2255            return
2256
2257        if (is_complex and complex.content.content.isRestriction() and
2258            complex.content.content.content is not None and
2259            complex.content.content.content.isModelGroup()):
2260
2261            self.mgContent = complex.content.content.content.content
2262            self.attrComponents = self._setAttributes(
2263                    complex.content.content.getAttributeContent()
2264                )
2265            return
2266
2267        if is_complex:
2268            self.mgContent = ()
2269            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2270            return
2271
2272        if complex.content.isModelGroup():
2273            self.mgContent = complex.content.content
2274            self.attrComponents = self._setAttributes(complex.getAttributeContent())
2275            return
2276
2277        # TODO: Scary Fallthru
2278        self.mgContent = ()
2279        self.attrComponents = self._setAttributes(complex.getAttributeContent())
2280
2281
2282class ElementGlobalDefContainer(TypecodeContainerBase):
2283    type = DEC
2284    logger = _GetLogger("ElementGlobalDefContainer")
2285
2286    def _substitutionGroupTag(self):
2287        value = self.substitutionGroup
2288        if not value:
2289            return 'substitutionGroup = None'
2290
2291        nsuri,ncname = value
2292        return 'substitutionGroup = ("%s","%s")' %(nsuri, ncname)
2293
2294    def _setContent(self):
2295        '''GED defines element name, so also define typecode aname
2296        '''
2297        kw = KW.copy()
2298        try:
2299            kw.update(dict(klass=self.getClassName(),
2300                       element='ElementDeclaration',
2301                       literal=self.literalTag(),
2302                       substitutionGroup=self._substitutionGroupTag(),
2303                       schema=self.schemaTag(),
2304                       init=self.simpleConstructor(),
2305                       ns=self.ns, name=self.name,
2306                       aname=self.getAttributeName(self.name),
2307                       baseslogic=self.getBasesLogic(ID3),
2308                       #ofwhat=self.getTypecodeList(),
2309                       #atypecode=self.attribute_typecode,
2310                       #pyclass=self.getPyClass(),
2311                       alias=NAD.getAlias(self.sKlassNS),
2312                       subclass=type_class_name(self.sKlass),
2313                       ))
2314        except Exception, ex:
2315            args = ['Failure processing an element w/local complexType: %s' %(
2316                          self._item.getItemTrace())]
2317            args += ex.args
2318            ex.args = tuple(args)
2319            raise
2320
2321        if self.local:
2322            kw['element'] = 'LocalElementDeclaration'
2323
2324        element = [
2325            '%(ID1)sclass %(klass)s(%(element)s):',
2326            '%(ID2)s%(literal)s',
2327            '%(ID2)s%(schema)s',
2328            '%(ID2)s%(substitutionGroup)s',
2329            '%(ID2)s%(init)s',
2330            '%(ID3)skw["pname"] = ("%(ns)s","%(name)s")',
2331            '%(ID3)skw["aname"] = "%(aname)s"',
2332            '%(baseslogic)s',
2333            '%(ID3)s%(alias)s.%(subclass)s.__init__(self, **kw)',
2334            '%(ID3)sif self.pyclass is not None: self.pyclass.__name__ = "%(klass)s_Holder"',
2335            ]
2336
2337        self.writeArray(map(lambda l: l %kw, element))
2338
2339    def setUp(self, element):
2340        # Save for debugging
2341        self._item = element
2342        self.local = element.isLocal()
2343        self.name = element.getAttribute('name')
2344        self.substitutionGroup = element.getAttribute('substitutionGroup')
2345        self.ns = element.getTargetNamespace()
2346        tp = element.getTypeDefinition('type')
2347        self.sKlass = tp.getAttribute('name')
2348        self.sKlassNS = tp.getTargetNamespace()
2349
2350
2351class ComplexTypeComplexContentContainer(TypecodeContainerBase, AttributeMixIn):
2352    '''Represents ComplexType with ComplexContent.
2353    '''
2354    type = DEF
2355    logger = _GetLogger("ComplexTypeComplexContentContainer")
2356
2357    def __init__(self, do_extended=False):
2358        TypecodeContainerBase.__init__(self, do_extended=do_extended)
2359
2360    def setUp(self, tp):
2361        '''complexContent/[extension,restriction]
2362            restriction
2363            extension
2364            extType -- used in figuring attrs for extensions
2365        '''
2366        self._item = tp
2367        assert tp.content.isComplex() is True and \
2368            (tp.content.content.isRestriction() or tp.content.content.isExtension() is True),\
2369            'expecting complexContent/[extension,restriction]'
2370
2371        self.extType = None
2372        self.restriction = False
2373        self.extension = False
2374        self._kw_array = None
2375        self._is_array = False
2376        self.name = tp.getAttribute('name')
2377        self.ns = tp.getTargetNamespace()
2378
2379        # xxx: what is this for?
2380        #self.attribute_typecode = 'attributes'
2381
2382        derivation = tp.content.content
2383        # Defined in Schema instance?
2384        try:
2385            base = derivation.getTypeDefinition('base')
2386        except XMLSchema.SchemaError, ex:
2387            base = None
2388
2389        # anyType, arrayType, etc...
2390        if base is None:
2391            base = derivation.getAttributeQName('base')
2392            if base is None:
2393                raise ContainerError, 'Unsupported derivation: %s'\
2394                        %derivation.getItemTrace()
2395
2396            if base != (SOAP.ENC,'Array') and base != (SCHEMA.XSD3,'anyType'):
2397                raise ContainerError, 'Unsupported base(%s): %s' %(
2398                    base, derivation.getItemTrace()
2399                    )
2400
2401        if base == (SOAP.ENC,'Array'):
2402            # SOAP-ENC:Array expecting arrayType attribute reference
2403            self.logger.debug("Derivation of soapenc:Array")
2404            self._is_array = True
2405            self._kw_array = {'atype':None, 'id3':ID3, 'ofwhat':None}
2406            self.sKlass = BTI.get_typeclass(base[1], base[0])
2407            self.sKlassNS = base[0]
2408
2409            for a in derivation.getAttributeContent():
2410
2411                assert a.isAttribute() is True,\
2412                    'only attribute content expected: %s' %a.getItemTrace()
2413
2414                if a.isReference() is False:
2415                    continue
2416
2417                if a.getAttribute('ref') != (SOAP.ENC,'arrayType'):
2418                    continue
2419
2420                attr = a.getAttributeQName((WSDL.BASE, 'arrayType'))
2421                if attr is None:
2422                    warnings.warn('soapenc:array derivation declares attribute reference ("%s","%s"), does not define attribute ("%s","%s")' %(
2423                        SOAP.ENC,'arrayType',WSDL.BASE, 'arrayType'))
2424                    break
2425
2426                self._kw_array['atype'] = attr
2427                qname = self._kw_array.get('atype')
2428                if a is not None:
2429                    ncname = qname[1].strip('[]')
2430                    namespace = qname[0]
2431                    try:
2432                        ofwhat = a.getSchemaItem(XMLSchema.TYPES, namespace, ncname)
2433                    except XMLSchema.SchemaError, ex:
2434                        ofwhat = None
2435
2436                    if ofwhat is None:
2437                        self._kw_array['ofwhat'] = BTI.get_typeclass(ncname, namespace)
2438                    else:
2439                        self._kw_array['ofwhat'] = GetClassNameFromSchemaItem(ofwhat, do_extended=self.do_extended)
2440
2441                    if self._kw_array['ofwhat'] is None:
2442                        raise ContainerError, 'For Array could not resolve ofwhat typecode(%s,%s): %s'\
2443                            %(namespace, ncname, derivation.getItemTrace())
2444
2445                    self.logger.debug('Attribute soapenc:arrayType="%s"' %
2446                                      str(self._kw_array['ofwhat']))
2447
2448                    break
2449
2450            #else:
2451            #    raise Wsdl2PythonError, \
2452            #        'derivation of soapenc:array must declare attribute reference ("%s","%s")' %(
2453            #        SOAP.ENC,'arrayType')
2454
2455
2456        elif isinstance(base, XMLSchema.XMLSchemaComponent):
2457            self.sKlass = base.getAttribute('name')
2458            self.sKlassNS = base.getTargetNamespace()
2459        else:
2460            # TypeDescriptionComponent
2461            self.sKlass = base.getName()
2462            self.sKlassNS = base.getTargetNamespace()
2463
2464        attrs = []
2465        if derivation.isRestriction():
2466            self.restriction = True
2467            self.extension = False
2468            # derivation.getAttributeContent subset of tp.getAttributeContent
2469            attrs += derivation.getAttributeContent() or ()
2470        else:
2471            self.restriction = False
2472            self.extension = True
2473            attrs += tp.getAttributeContent() or ()
2474            if isinstance(derivation, XMLSchema.XMLSchemaComponent):
2475                attrs += derivation.getAttributeContent() or ()
2476
2477        # XXX: not sure what this is doing
2478        if attrs:
2479            self.extType = derivation
2480
2481        if derivation.content is not None \
2482            and derivation.content.isModelGroup():
2483            group = derivation.content
2484            if group.isReference():
2485                group = group.getModelGroupReference()
2486            self.mgContent = group.content
2487        elif derivation.content:
2488            raise Wsdl2PythonError, \
2489                'expecting model group, not: %s' %derivation.content.getItemTrace()
2490        else:
2491            self.mgContent = ()
2492
2493        self.attrComponents = self._setAttributes(tuple(attrs))
2494
2495    def _setContent(self):
2496        '''JRB What is the difference between instance data
2497        ns, name, -- type definition?
2498        sKlass, sKlassNS? -- element declaration?
2499        '''
2500        kw = KW.copy()
2501        definition = []
2502        if self._is_array:
2503            # SOAP-ENC:Array
2504            if _is_xsd_or_soap_ns(self.sKlassNS) is False and self.sKlass == 'Array':
2505                raise ContainerError, 'unknown type: (%s,%s)'\
2506                    %(self.sKlass, self.sKlassNS)
2507
2508            # No need to xsi:type array items since specify with
2509            # SOAP-ENC:arrayType attribute.
2510            definition += [\
2511                '%sclass %s(ZSI.TC.Array, TypeDefinition):' % (ID1, self.getClassName()),
2512                '%s#complexType/complexContent base="SOAP-ENC:Array"' %(ID2),
2513                '%s%s' % (ID2, self.schemaTag()),
2514                '%s%s' % (ID2, self.typeTag()),
2515                '%s%s' % (ID2, self.pnameConstructor()),
2516                ]
2517
2518            append = definition.append
2519            if  self._kw_array.get('ofwhat') is None:
2520                append('%s%s.__init__(self, None, None, pname=pname, childnames=\'item\', undeclared=True, **kw)' %(ID3, self.sKlass))
2521            else:
2522                append('%(id3)sofwhat = %(ofwhat)s(None, typed=False)' %self._kw_array)
2523                append('%(id3)satype = %(atype)s' %self._kw_array)
2524                append('%s%s.__init__(self, atype, ofwhat, pname=pname, childnames=\'item\', **kw)' %(ID3, self.sKlass))
2525
2526            self.writeArray(definition)
2527            return
2528
2529        definition += [\
2530            '%sclass %s(TypeDefinition):' % (ID1, self.getClassName()),
2531            '%s%s' % (ID2, self.schemaTag()),
2532            '%s%s' % (ID2, self.typeTag()),
2533            '%s%s' % (ID2, self.pnameConstructor()),
2534            '%s%s' % (ID3, self.nsuriLogic()),
2535            '%sTClist = [%s]' % (ID3, self.getTypecodeList()),
2536            ]
2537
2538        definition.append(
2539            '%(ID3)sattributes = %(atc)s = attributes or {}' %{
2540                'ID3':ID3, 'atc':self.attribute_typecode}
2541        )
2542
2543        #
2544        # Special case: anyType restriction
2545        isAnyType = (self.sKlassNS, self.sKlass) == (SCHEMA.XSD3, 'anyType')
2546        if isAnyType:
2547            del definition[0]
2548            definition.insert(0,
2549                '%sclass %s(ZSI.TC.ComplexType, TypeDefinition):' % (
2550                             ID1, self.getClassName())
2551            )
2552            definition.insert(1,
2553                '%s#complexType/complexContent restrict anyType' %(
2554                               ID2)
2555            )
2556
2557        # derived type support
2558        definition.append('%sif extend: TClist += ofwhat'%(ID3))
2559        definition.append('%sif restrict: TClist = ofwhat' %(ID3))
2560        if len(self.attrComponents) > 0:
2561            definition.append('%selse:' %(ID3))
2562            for l in self.attrComponents:
2563                definition.append('%s%s'%(ID4, l))
2564
2565        if isAnyType:
2566            definition.append(\
2567                '%sZSI.TC.ComplexType.__init__(self, None, TClist, pname=pname, **kw)' %(
2568                    ID3),
2569            )
2570
2571            # pyclass class definition
2572            definition += self.getPyClassDefinition()
2573            kw['pyclass'] = self.getPyClass()
2574            definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw)
2575            self.writeArray(definition)
2576            return
2577
2578        definition.append('%s'   % self.getBasesLogic(ID3))
2579        prefix = NAD.getAlias(self.sKlassNS)
2580        typeClassName = type_class_name(self.sKlass)
2581        if self.restriction:
2582            definition.append(\
2583                '%s%s.%s.__init__(self, pname, ofwhat=TClist, restrict=True, **kw)' %(
2584                    ID3, prefix, typeClassName),
2585            )
2586            definition.insert(1, '%s#complexType/complexContent restriction' %ID2)
2587            self.writeArray(definition)
2588            return
2589
2590        if self.extension:
2591            definition.append(\
2592                '%s%s.%s.__init__(self, pname, ofwhat=TClist, extend=True, attributes=attributes, **kw)'%(
2593                    ID3, prefix, typeClassName),
2594            )
2595            definition.insert(1, '%s#complexType/complexContent extension' %(ID2))
2596            self.writeArray(definition)
2597            return
2598
2599        raise Wsdl2PythonError,\
2600            'ComplexContent must be a restriction or extension'
2601
2602    def pnameConstructor(self, superclass=None):
2603        if superclass:
2604            return '%s.__init__(self, pname, ofwhat=(), extend=False, restrict=False, attributes=None, **kw)' % superclass
2605
2606        return 'def __init__(self, pname, ofwhat=(), extend=False, restrict=False, attributes=None, **kw):'
2607
2608
2609class ComplexTypeContainer(TypecodeContainerBase, AttributeMixIn):
2610    '''Represents a global complexType definition.
2611    '''
2612    type = DEF
2613    logger = _GetLogger("ComplexTypeContainer")
2614
2615    def setUp(self, tp, empty=False):
2616        '''Problematic, loose all model group information.
2617        <all>, <choice>, <sequence> ..
2618
2619           tp -- type definition
2620           empty -- no model group, just use as a dummy holder.
2621        '''
2622        self._item = tp
2623
2624        self.name = tp.getAttribute('name')
2625        self.ns = tp.getTargetNamespace()
2626        self.mixed = tp.isMixed()
2627        self.mgContent = ()
2628        self.attrComponents = self._setAttributes(tp.getAttributeContent())
2629
2630        # Save reference to type for debugging
2631        self._item = tp
2632
2633        if empty:
2634            return
2635
2636        model = tp.content
2637        if model.isReference():
2638            model = model.getModelGroupReference()
2639
2640        if model is None:
2641            return
2642
2643        if model.content is None:
2644            return
2645
2646        # sequence, all or choice
2647        #self.mgContent = model.content
2648        self.mgContent = model
2649
2650    def _setContent(self):
2651        try:
2652            definition = [
2653                '%sclass %s(ZSI.TCcompound.ComplexType, TypeDefinition):'
2654                % (ID1, self.getClassName()),
2655                '%s%s' % (ID2, self.schemaTag()),
2656                '%s%s' % (ID2, self.typeTag()),
2657                '%s%s' % (ID2, self.pnameConstructor()),
2658                #'%s'   % self.getElements(),
2659                '%s%s' % (ID3, self.nsuriLogic()),
2660                '%sTClist = [%s]' % (ID3, self.getTypecodeList()),
2661                ]
2662        except Exception, ex:
2663            args = ["Failure processing %s" %self._item.getItemTrace()]
2664            args += ex.args
2665            ex.args = tuple(args)
2666            raise
2667
2668        definition.append('%s%s = attributes or {}' %(ID3,
2669                           self.attribute_typecode))
2670        # IF EXTEND
2671        definition.append('%sif extend: TClist += ofwhat'%(ID3))
2672        # IF RESTRICT
2673        definition.append('%sif restrict: TClist = ofwhat' %(ID3))
2674        # ELSE
2675        if len(self.attrComponents) > 0:
2676            definition.append('%selse:' %(ID3))
2677            for l in self.attrComponents:  definition.append('%s%s'%(ID4, l))
2678
2679        definition.append(\
2680            '%sZSI.TCcompound.ComplexType.__init__(self, None, TClist, pname=pname, inorder=0, %s**kw)' \
2681            %(ID3, self.getExtraFlags())
2682        )
2683
2684        # pyclass class definition
2685        definition += self.getPyClassDefinition()
2686
2687        # set pyclass
2688        kw = KW.copy()
2689        kw['pyclass'] = self.getPyClass()
2690        definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw)
2691        self.writeArray(definition)
2692
2693    def pnameConstructor(self, superclass=None):
2694        ''' TODO: Logic is a little tricky.  If superclass is ComplexType this is not used.
2695        '''
2696        if superclass:
2697            return '%s.__init__(self, pname, ofwhat=(), attributes=None, extend=False, restrict=False, **kw)' % superclass
2698
2699        return 'def __init__(self, pname, ofwhat=(), attributes=None, extend=False, restrict=False, **kw):'
2700
2701
2702class SimpleTypeContainer(TypecodeContainerBase):
2703    type = DEF
2704    logger = _GetLogger("SimpleTypeContainer")
2705
2706    def __init__(self):
2707        '''
2708        Instance Data From TypecodeContainerBase NOT USED...
2709           mgContent
2710        '''
2711        TypecodeContainerBase.__init__(self)
2712
2713    def setUp(self, tp):
2714        raise NotImplementedError, 'abstract method not implemented'
2715
2716    def _setContent(self, tp):
2717        raise NotImplementedError, 'abstract method not implemented'
2718
2719    def getPythonType(self):
2720        pyclass = eval(str(self.sKlass))
2721        if issubclass(pyclass, ZSI.TC.String):
2722            return 'str'
2723        if issubclass(pyclass, ZSI.TC.Ilong) or issubclass(pyclass, ZSI.TC.IunsignedLong):
2724            return 'long'
2725        if issubclass(pyclass, ZSI.TC.Boolean) or issubclass(pyclass, ZSI.TC.Integer):
2726            return 'int'
2727        if issubclass(pyclass, ZSI.TC.Decimal):
2728            return 'float'
2729        if issubclass(pyclass, ZSI.TC.Gregorian) or issubclass(pyclass, ZSI.TC.Duration):
2730            return 'tuple'
2731        return None
2732
2733    def getPyClassDefinition(self):
2734        definition = []
2735        pt = self.getPythonType()
2736        if pt is not None:
2737            definition.append('%sclass %s(%s):' %(ID3,self.getPyClass(),pt))
2738            definition.append('%stypecode = self' %ID4)
2739        return definition
2740
2741
2742class RestrictionContainer(SimpleTypeContainer):
2743    '''
2744       simpleType/restriction
2745    '''
2746    logger = _GetLogger("RestrictionContainer")
2747
2748    def setUp(self, tp):
2749        self._item = tp
2750
2751        assert tp.isSimple() is True and tp.isDefinition() is True and \
2752            tp.content.isRestriction() is True,\
2753            'expecting simpleType restriction, not: %s' %tp.getItemTrace()
2754
2755        if tp.content is None:
2756            raise Wsdl2PythonError, \
2757                  'empty simpleType defintion: %s' %tp.getItemTrace()
2758
2759        self.name = tp.getAttribute('name')
2760        self.ns = tp.getTargetNamespace()
2761        self.sKlass = None
2762
2763        base = tp.content.getAttribute('base')
2764        if base is not None:
2765            try:
2766                item = tp.content.getTypeDefinition('base')
2767            except XMLSchema.SchemaError, ex:
2768                item = None
2769
2770            if item is None:
2771                self.sKlass = BTI.get_typeclass(base.getName(), base.getTargetNamespace())
2772                if self.sKlass is not None:
2773                    return
2774
2775                raise Wsdl2PythonError('no built-in type nor schema instance type for base attribute("%s","%s"): %s' %(
2776                    base.getTargetNamespace(), base.getName(), tp.getItemTrace()))
2777
2778            raise Wsdl2PythonError, \
2779                'Not Supporting simpleType/Restriction w/User-Defined Base: %s %s' %(tp.getItemTrace(),item.getItemTrace())
2780
2781        sc = tp.content.getSimpleTypeContent()
2782        if sc is not None and True is sc.isSimple() is sc.isLocal() is sc.isDefinition():
2783            base = None
2784            if sc.content.isRestriction() is True:
2785                try:
2786                    item = tp.content.getTypeDefinition('base')
2787                except XMLSchema.SchemaError, ex:
2788                    pass
2789
2790                if item is None:
2791                    base = sc.content.getAttribute('base')
2792                    if base is not None:
2793                        self.sKlass = BTI.get_typeclass(base.getTargetNamespace(), base.getName())
2794                        return
2795                    raise Wsdl2PythonError, \
2796                        'Not Supporting simpleType/Restriction w/User-Defined Base: '\
2797                        %item.getItemTrace()
2798
2799                raise Wsdl2PythonError, \
2800                    'Not Supporting simpleType/Restriction w/User-Defined Base: '\
2801                    %item.getItemTrace()
2802
2803            if sc.content.isList() is True:
2804                raise Wsdl2PythonError, \
2805                      'iction base in subtypes: %s'\
2806                      %sc.getItemTrace()
2807
2808            if sc.content.isUnion() is True:
2809                raise Wsdl2PythonError, \
2810                      'could not get restriction base in subtypes: %s'\
2811                      %sc.getItemTrace()
2812
2813            return
2814
2815        raise Wsdl2PythonError, 'No Restriction @base/simpleType: %s' %tp.getItemTrace()
2816
2817    def _setContent(self):
2818
2819        definition = [
2820            '%sclass %s(%s, TypeDefinition):' %(ID1, self.getClassName(),
2821                         self.sKlass),
2822            '%s%s' % (ID2, self.schemaTag()),
2823            '%s%s' % (ID2, self.typeTag()),
2824            '%s%s' % (ID2, self.pnameConstructor()),
2825        ]
2826        if self.getPythonType() is None:
2827            definition.append('%s%s.__init__(self, pname, **kw)' %(ID3,
2828                               self.sKlass))
2829        else:
2830            definition.append('%s%s.__init__(self, pname, pyclass=None, **kw)' \
2831                               %(ID3, self.sKlass,))
2832
2833            # pyclass class definition
2834            definition += self.getPyClassDefinition()
2835
2836            # set pyclass
2837            kw = KW.copy()
2838            kw['pyclass'] = self.getPyClass()
2839            definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw)
2840
2841        self.writeArray(definition)
2842
2843
2844class ComplexTypeSimpleContentContainer(SimpleTypeContainer, AttributeMixIn):
2845    '''Represents a ComplexType with simpleContent.
2846    '''
2847    type = DEF
2848    logger = _GetLogger("ComplexTypeSimpleContentContainer")
2849
2850    def setUp(self, tp):
2851        '''tp -- complexType/simpleContent/[Exention,Restriction]
2852        '''
2853        self._item = tp
2854
2855        assert tp.isComplex() is True and tp.content.isSimple() is True,\
2856            'expecting complexType/simpleContent not: %s' %tp.content.getItemTrace()
2857
2858        simple = tp.content
2859        dv = simple.content
2860        assert dv.isExtension() is True or dv.isRestriction() is True,\
2861            'expecting complexType/simpleContent/[Extension,Restriction] not: %s' \
2862            %tp.content.getItemTrace()
2863
2864        self.name = tp.getAttribute('name')
2865        self.ns = tp.getTargetNamespace()
2866        # TODO: Why is this being set?
2867        self.content.attributeContent = dv.getAttributeContent()
2868
2869        base = dv.getAttribute('base')
2870        if base is not None:
2871            self.sKlass = BTI.get_typeclass( base[1], base[0] )
2872            if not self.sKlass:
2873                self.sKlass,self.sKlassNS = base[1], base[0]
2874
2875            self.attrComponents = self._setAttributes(
2876                                      self.content.attributeContent
2877                                      )
2878            return
2879
2880        raise Wsdl2PythonError,\
2881            'simple content derivation bad base attribute: ' %tp.getItemTrace()
2882
2883    def _setContent(self):
2884        # TODO: Add derivation logic to constructors.
2885        if type(self.sKlass) in (types.ClassType, type):
2886            definition = [
2887                '%sclass %s(%s, TypeDefinition):' \
2888                % (ID1, self.getClassName(), self.sKlass),
2889                '%s# ComplexType/SimpleContent derivation of built-in type' %ID2,
2890                '%s%s' % (ID2, self.schemaTag()),
2891                '%s%s' % (ID2, self.typeTag()),
2892                '%s%s' % (ID2, self.pnameConstructor()),
2893                '%sif getattr(self, "attribute_typecode_dict", None) is None: %s = {}' %(
2894                    ID3, self.attribute_typecode),
2895                ]
2896
2897            for l in self.attrComponents:
2898                definition.append('%s%s'%(ID3, l))
2899
2900            definition.append('%s%s.__init__(self, pname, **kw)' %(ID3, self.sKlass))
2901            if self.getPythonType() is not None:
2902                definition += self.getPyClassDefinition()
2903                kw = KW.copy()
2904                kw['pyclass'] = self.getPyClass()
2905                definition.append('%(ID3)sself.pyclass = %(pyclass)s' %kw)
2906
2907            self.writeArray(definition)
2908            return
2909
2910        definition = [
2911            '%sclass %s(TypeDefinition):' % (ID1, self.getClassName()),
2912            '%s# ComplexType/SimpleContent derivation of user-defined type' %ID2,
2913            '%s%s' % (ID2, self.schemaTag()),
2914            '%s%s' % (ID2, self.typeTag()),
2915            '%s%s' % (ID2, self.pnameConstructor()),
2916            '%s%s' % (ID3, self.nsuriLogic()),
2917            '%s'   % self.getBasesLogic(ID3),
2918            '%sif getattr(self, "attribute_typecode_dict", None) is None: %s = {}' %(
2919                ID3, self.attribute_typecode),
2920            ]
2921
2922        for l in self.attrComponents:
2923            definition.append('%s%s'%(ID3, l))
2924
2925        definition.append('%s%s.%s.__init__(self, pname, **kw)' %(
2926            ID3, NAD.getAlias(self.sKlassNS), type_class_name(self.sKlass)))
2927
2928        self.writeArray(definition)
2929
2930    def getPyClassDefinition(self):
2931        definition = []
2932        pt = self.getPythonType()
2933        if pt is not None:
2934            definition.append('%sclass %s(%s):' %(ID3,self.getPyClass(),pt))
2935            if self.metaclass is not None:
2936                definition.append('%s__metaclass__ = %s' %(ID4, self.metaclass))
2937
2938            definition.append('%stypecode = self' %ID4)
2939        return definition
2940
2941
2942
2943
2944
2945class UnionContainer(SimpleTypeContainer):
2946    '''SimpleType Union
2947    '''
2948    type = DEF
2949    logger = _GetLogger("UnionContainer")
2950
2951    def __init__(self):
2952        SimpleTypeContainer.__init__(self)
2953        self.memberTypes = None
2954
2955    def setUp(self, tp):
2956        self._item = tp
2957
2958        if tp.content.isUnion() is False:
2959            raise ContainerError, 'content must be a Union: %s' %tp.getItemTrace()
2960        self.name = tp.getAttribute('name')
2961        self.ns = tp.getTargetNamespace()
2962        self.sKlass = 'ZSI.TC.Union'
2963        self.memberTypes = tp.content.getAttribute('memberTypes')
2964
2965    def _setContent(self):
2966        definition = [
2967            '%sclass %s(%s, TypeDefinition):' \
2968            % (ID1, self.getClassName(), self.sKlass),
2969            '%smemberTypes = %s' % (ID2, self.memberTypes),
2970            '%s%s' % (ID2, self.schemaTag()),
2971            '%s%s' % (ID2, self.typeTag()),
2972            '%s%s' % (ID2, self.pnameConstructor()),
2973            '%s%s' % (ID3, self.pnameConstructor(self.sKlass)),
2974            ]
2975
2976        # TODO: Union pyclass is None
2977        self.writeArray(definition)
2978
2979
2980class ListContainer(SimpleTypeContainer):
2981    '''SimpleType List
2982    '''
2983    type = DEF
2984    logger = _GetLogger("ListContainer")
2985
2986    def setUp(self, tp):
2987        self._item = tp
2988
2989        if tp.content.isList() is False:
2990            raise ContainerError, 'content must be a List: %s' %tp.getItemTrace()
2991        self.name = tp.getAttribute('name')
2992        self.ns = tp.getTargetNamespace()
2993        self.sKlass = 'ZSI.TC.List'
2994        self.itemType = tp.content.getAttribute('itemType')
2995
2996    def _setContent(self):
2997        definition = [
2998            '%sclass %s(%s, TypeDefinition):' \
2999            % (ID1, self.getClassName(), self.sKlass),
3000            '%sitemType = %s' % (ID2, self.itemType),
3001            '%s%s' % (ID2, self.schemaTag()),
3002            '%s%s' % (ID2, self.typeTag()),
3003            '%s%s' % (ID2, self.pnameConstructor()),
3004            '%s%s' % (ID3, self.pnameConstructor(self.sKlass)),
3005            ]
3006        self.writeArray(definition)
3007
3008
3009