1# This program is free software; you can redistribute it and/or modify 2# it under the terms of the (LGPL) GNU Lesser General Public License as 3# published by the Free Software Foundation; either version 3 of the 4# License, or (at your option) any later version. 5# 6# This program is distributed in the hope that it will be useful, 7# but WITHOUT ANY WARRANTY; without even the implied warranty of 8# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9# GNU Library Lesser General Public License for more details at 10# ( http://www.gnu.org/licenses/lgpl.html ). 11# 12# You should have received a copy of the GNU Lesser General Public License 13# along with this program; if not, write to the Free Software 14# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15# written by: Jeff Ortel ( jortel@redhat.com ) 16 17""" 18Provides encoded I{marshaller} classes. 19""" 20 21from suds import * 22from suds.mx import * 23from suds.mx.literal import Literal 24from suds.mx.typer import Typer 25from suds.sudsobject import Factory, Object 26from suds.xsd.query import TypeQuery 27 28 29# 30# Add encoded extensions 31# aty = The soap (section 5) encoded array type. 32# 33Content.extensions.append('aty') 34 35 36class Encoded(Literal): 37 """ 38 A SOAP section (5) encoding marshaller. 39 This marshaller supports rpc/encoded soap styles. 40 """ 41 42 def start(self, content): 43 # 44 # For soap encoded arrays, the 'aty' (array type) information 45 # is extracted and added to the 'content'. Then, the content.value 46 # is replaced with an object containing an 'item=[]' attribute 47 # containing values that are 'typed' suds objects. 48 # 49 start = Literal.start(self, content) 50 if start and isinstance(content.value, (list,tuple)): 51 resolved = content.type.resolve() 52 for c in resolved: 53 if hasattr(c[0], 'aty'): 54 content.aty = (content.tag, c[0].aty) 55 self.cast(content) 56 break 57 return start 58 59 def end(self, parent, content): 60 # 61 # For soap encoded arrays, the soapenc:arrayType attribute is 62 # added with proper type and size information. 63 # Eg: soapenc:arrayType="xs:int[3]" 64 # 65 Literal.end(self, parent, content) 66 if content.aty is None: 67 return 68 tag, aty = content.aty 69 ns0 = ('at0', aty[1]) 70 ns1 = ('at1', 'http://schemas.xmlsoap.org/soap/encoding/') 71 array = content.value.item 72 child = parent.getChild(tag) 73 child.addPrefix(ns0[0], ns0[1]) 74 child.addPrefix(ns1[0], ns1[1]) 75 name = '%s:arrayType' % ns1[0] 76 value = '%s:%s[%d]' % (ns0[0], aty[0], len(array)) 77 child.set(name, value) 78 79 def encode(self, node, content): 80 if content.type.any(): 81 Typer.auto(node, content.value) 82 return 83 if content.real.any(): 84 Typer.auto(node, content.value) 85 return 86 ns = None 87 name = content.real.name 88 if self.xstq: 89 ns = content.real.namespace() 90 Typer.manual(node, name, ns) 91 92 def cast(self, content): 93 """ 94 Cast the I{untyped} list items found in content I{value}. 95 Each items contained in the list is checked for XSD type information. 96 Items (values) that are I{untyped}, are replaced with suds objects and 97 type I{metadata} is added. 98 @param content: The content holding the collection. 99 @type content: L{Content} 100 @return: self 101 @rtype: L{Encoded} 102 """ 103 aty = content.aty[1] 104 resolved = content.type.resolve() 105 array = Factory.object(resolved.name) 106 array.item = [] 107 query = TypeQuery(aty) 108 ref = query.execute(self.schema) 109 if ref is None: 110 raise TypeNotFound(qref) 111 for x in content.value: 112 if isinstance(x, (list, tuple)): 113 array.item.append(x) 114 continue 115 if isinstance(x, Object): 116 md = x.__metadata__ 117 md.sxtype = ref 118 array.item.append(x) 119 continue 120 if isinstance(x, dict): 121 x = Factory.object(ref.name, x) 122 md = x.__metadata__ 123 md.sxtype = ref 124 array.item.append(x) 125 continue 126 x = Factory.property(ref.name, x) 127 md = x.__metadata__ 128 md.sxtype = ref 129 array.item.append(x) 130 content.value = array 131 return self 132