| Class | SOAP::EncodingStyle::SOAPHandler |
| In: |
lib/soap/encodingstyle/soapHandler.rb
|
| Parent: | Handler |
| Namespace | = | SOAP::EncodingNamespace |
| NilLiteralMap | = | { 'true' => true, '1' => true, 'false' => false, '0' => false |
| RootLiteralMap | = | { '1' => 1, '0' => 0 |
# File lib/soap/encodingstyle/soapHandler.rb, line 20
20: def initialize(charset = nil)
21: super(charset)
22: @refpool = []
23: @idpool = []
24: @textbuf = ''
25: @is_first_top_ele = true
26: end
# File lib/soap/encodingstyle/soapHandler.rb, line 211
211: def decode_epilogue
212: decode_resolve_id
213: end
# File lib/soap/encodingstyle/soapHandler.rb, line 215
215: def decode_parent(parent, node)
216: return unless parent.node
217: case parent.node
218: when SOAPUnknown
219: newparent = parent.node.as_struct
220: node.parent = newparent
221: if newparent.id
222: @idpool << newparent
223: end
224: parent.replace_node(newparent)
225: decode_parent(parent, node)
226: when SOAPStruct
227: parent.node.add(node.elename.name, node)
228: node.parent = parent.node
229: when SOAPArray
230: if node.position
231: parent.node[*(decode_arypos(node.position))] = node
232: parent.node.sparse = true
233: else
234: parent.node.add(node)
235: end
236: node.parent = parent.node
237: else
238: raise EncodingStyleError.new("illegal parent: #{parent.node}")
239: end
240: end
# File lib/soap/encodingstyle/soapHandler.rb, line 205
205: def decode_prologue
206: @refpool.clear
207: @idpool.clear
208: @is_first_top_ele = true
209: end
# File lib/soap/encodingstyle/soapHandler.rb, line 145
145: def decode_tag(ns, elename, attrs, parent)
146: @textbuf = ''
147: is_nil, type, arytype, root, offset, position, href, id, extraattr =
148: decode_attrs(ns, attrs)
149: o = nil
150: if is_nil
151: o = SOAPNil.decode(elename)
152: elsif href
153: o = SOAPReference.decode(elename, href)
154: @refpool << o
155: elsif @decode_typemap
156: o = decode_tag_by_wsdl(ns, elename, type, parent.node, arytype, extraattr)
157: else
158: o = decode_tag_by_type(ns, elename, type, parent.node, arytype, extraattr)
159: end
160:
161: if o.is_a?(SOAPArray)
162: if offset
163: o.offset = decode_arypos(offset)
164: o.sparse = true
165: else
166: o.sparse = false
167: end
168: end
169:
170: o.parent = parent
171: o.id = id
172: o.root = root
173: o.position = position
174:
175: unless o.is_a?(SOAPTemporalObject)
176: @idpool << o if o.id
177: decode_parent(parent, o)
178: end
179: o
180: end
# File lib/soap/encodingstyle/soapHandler.rb, line 182
182: def decode_tag_end(ns, node)
183: o = node.node
184: if o.is_a?(SOAPUnknown)
185: newnode = if /\A\s*\z/ =~ @textbuf
186: o.as_struct
187: else
188: o.as_string
189: end
190: if newnode.id
191: @idpool << newnode
192: end
193: node.replace_node(newnode)
194: o = node.node
195: end
196: decode_textbuf(o)
197: # unlink definedtype
198: o.definedtype = nil
199: end
# File lib/soap/encodingstyle/soapHandler.rb, line 201
201: def decode_text(ns, text)
202: @textbuf << text
203: end
encode interface.
# File lib/soap/encodingstyle/soapHandler.rb, line 32
32: def encode_data(generator, ns, data, parent)
33: attrs = encode_attrs(generator, ns, data, parent)
34: if parent && parent.is_a?(SOAPArray) && parent.position
35: attrs[ns.name(AttrPositionName)] = "[#{parent.position.join(',')}]"
36: end
37: name = generator.encode_name(ns, data, attrs)
38: case data
39: when SOAPReference
40: attrs['href'] = data.refidstr
41: generator.encode_tag(name, attrs)
42: when SOAPExternalReference
43: data.referred
44: attrs['href'] = data.refidstr
45: generator.encode_tag(name, attrs)
46: when SOAPRawString
47: generator.encode_tag(name, attrs)
48: generator.encode_rawstring(data.to_s)
49: when XSD::XSDString
50: generator.encode_tag(name, attrs)
51: generator.encode_string(@charset ?
52: XSD::Charset.encoding_to_xml(data.to_s, @charset) : data.to_s)
53: when XSD::XSDAnySimpleType
54: generator.encode_tag(name, attrs)
55: generator.encode_string(data.to_s)
56: when SOAPStruct
57: generator.encode_tag(name, attrs)
58: data.each do |key, value|
59: generator.encode_child(ns, value, data)
60: end
61: when SOAPArray
62: generator.encode_tag(name, attrs)
63: data.traverse do |child, *rank|
64: data.position = data.sparse ? rank : nil
65: generator.encode_child(ns, child, data)
66: end
67: else
68: raise EncodingStyleError.new(
69: "unknown object:#{data} in this encodingStyle")
70: end
71: end
# File lib/soap/encodingstyle/soapHandler.rb, line 73
73: def encode_data_end(generator, ns, data, parent)
74: name = generator.encode_name_end(ns, data)
75: cr = data.is_a?(SOAPCompoundtype)
76: generator.encode_tag_end(name, cr)
77: end
# File lib/soap/encodingstyle/soapHandler.rb, line 244
244: def content_ranksize(typename)
245: typename.scan(/\[[\d,]*\]$/)[0]
246: end
# File lib/soap/encodingstyle/soapHandler.rb, line 248
248: def content_typename(typename)
249: typename.sub(/\[,*\]$/, '')
250: end
# File lib/soap/encodingstyle/soapHandler.rb, line 252
252: def create_arytype(ns, data)
253: XSD::QName.new(data.arytype.namespace,
254: content_typename(data.arytype.name) + "[#{data.size.join(',')}]")
255: end
# File lib/soap/encodingstyle/soapHandler.rb, line 549
549: def decode_arypos(position)
550: /^\[(.+)\]$/ =~ position
551: $1.split(',').collect { |s| s.to_i }
552: end
# File lib/soap/encodingstyle/soapHandler.rb, line 539
539: def decode_attr_value(ns, qname, value)
540: if /\A#/ =~ value
541: o = SOAPReference.decode(nil, value)
542: @refpool << o
543: o
544: else
545: value
546: end
547: end
# File lib/soap/encodingstyle/soapHandler.rb, line 483
483: def decode_attrs(ns, attrs)
484: is_nil = false
485: type = nil
486: arytype = nil
487: root = nil
488: offset = nil
489: position = nil
490: href = nil
491: id = nil
492: extraattr = {}
493:
494: attrs.each do |key, value|
495: qname = ns.parse(key)
496: case qname.namespace
497: when XSD::InstanceNamespace
498: case qname.name
499: when XSD::NilLiteral
500: is_nil = NilLiteralMap[value] or
501: raise EncodingStyleError.new("cannot accept attribute value: #{value} as the value of xsi:#{XSD::NilLiteral} (expected 'true', 'false', '1', or '0')")
502: next
503: when XSD::AttrType
504: type = value
505: next
506: end
507: when EncodingNamespace
508: case qname.name
509: when AttrArrayType
510: arytype = value
511: next
512: when AttrRoot
513: root = RootLiteralMap[value] or
514: raise EncodingStyleError.new(
515: "illegal root attribute value: #{value}")
516: next
517: when AttrOffset
518: offset = value
519: next
520: when AttrPosition
521: position = value
522: next
523: end
524: end
525: if key == 'href'
526: href = value
527: next
528: elsif key == 'id'
529: id = value
530: next
531: end
532: qname = ns.parse_local(key)
533: extraattr[qname] = decode_attr_value(ns, qname, value)
534: end
535:
536: return is_nil, type, arytype, root, offset, position, href, id, extraattr
537: end
# File lib/soap/encodingstyle/soapHandler.rb, line 380
380: def decode_basetype(klass, elename)
381: klass.decode(elename)
382: end
# File lib/soap/encodingstyle/soapHandler.rb, line 390
390: def decode_defined_complextype(elename, typename, typedef, arytypestr)
391: case typedef.compoundtype
392: when :TYPE_STRUCT, :TYPE_MAP
393: o = SOAPStruct.decode(elename, typename)
394: o.definedtype = typedef
395: return o
396: when :TYPE_ARRAY
397: expected_arytype = typedef.find_arytype
398: if arytypestr
399: actual_arytype = XSD::QName.new(expected_arytype.namespace,
400: content_typename(expected_arytype.name) <<
401: content_ranksize(arytypestr))
402: o = SOAPArray.decode(elename, typename, actual_arytype)
403: else
404: o = SOAPArray.new(typename, 1, expected_arytype)
405: o.elename = elename
406: end
407: o.definedtype = typedef
408: return o
409: when :TYPE_EMPTY
410: o = SOAPNil.decode(elename)
411: o.definedtype = typedef
412: return o
413: else
414: raise RuntimeError.new(
415: "Unknown kind of complexType: #{typedef.compoundtype}")
416: end
417: nil
418: end
# File lib/soap/encodingstyle/soapHandler.rb, line 384
384: def decode_defined_simpletype(elename, typename, typedef, arytypestr)
385: o = decode_basetype(TypeMap[typedef.base], elename)
386: o.definedtype = typedef
387: o
388: end
# File lib/soap/encodingstyle/soapHandler.rb, line 369
369: def decode_definedtype(elename, typename, typedef, arytypestr)
370: unless typedef
371: raise EncodingStyleError.new("unknown type '#{typename}'")
372: end
373: if typedef.is_a?(::WSDL::XMLSchema::SimpleType)
374: decode_defined_simpletype(elename, typename, typedef, arytypestr)
375: else
376: decode_defined_complextype(elename, typename, typedef, arytypestr)
377: end
378: end
# File lib/soap/encodingstyle/soapHandler.rb, line 554
554: def decode_resolve_id
555: count = @refpool.length # To avoid infinite loop
556: while !@refpool.empty? && count > 0
557: @refpool = @refpool.find_all { |ref|
558: o = @idpool.find { |item|
559: item.id == ref.refid
560: }
561: if o.is_a?(SOAPReference)
562: true # link of link.
563: elsif o
564: ref.__setobj__(o)
565: false
566: elsif o = ref.rootnode.external_content[ref.refid]
567: ref.__setobj__(o)
568: false
569: else
570: raise EncodingStyleError.new("unresolved reference: #{ref.refid}")
571: end
572: }
573: count -= 1
574: end
575: end
# File lib/soap/encodingstyle/soapHandler.rb, line 420
420: def decode_tag_by_type(ns, elename, typestr, parent, arytypestr, extraattr)
421: if arytypestr
422: type = typestr ? ns.parse(typestr) : ValueArrayName
423: node = SOAPArray.decode(elename, type, ns.parse(arytypestr))
424: node.extraattr.update(extraattr)
425: return node
426: end
427:
428: type = nil
429: if typestr
430: type = ns.parse(typestr)
431: elsif parent.is_a?(SOAPArray)
432: type = parent.arytype
433: else
434: # Since it's in dynamic(without any type) encoding process,
435: # assumes entity as its type itself.
436: # <SOAP-ENC:Array ...> => type Array in SOAP-ENC.
437: # <Country xmlns="foo"> => type Country in foo.
438: type = elename
439: end
440:
441: if (klass = TypeMap[type])
442: node = decode_basetype(klass, elename)
443: node.extraattr.update(extraattr)
444: return node
445: end
446:
447: # Unknown type... Struct or String
448: SOAPUnknown.new(self, elename, type, extraattr)
449: end
# File lib/soap/encodingstyle/soapHandler.rb, line 313
313: def decode_tag_by_wsdl(ns, elename, typestr, parent, arytypestr, extraattr)
314: o = nil
315: if parent.class == SOAPBody
316: # root element: should branch by root attribute?
317: if @is_first_top_ele
318: # Unqualified name is allowed here.
319: @is_first_top_ele = false
320: type = @decode_typemap[elename] ||
321: @decode_typemap.find_name(elename.name)
322: if type
323: o = SOAPStruct.new(elename)
324: o.definedtype = type
325: return o
326: end
327: end
328: # multi-ref element.
329: if typestr
330: typename = ns.parse(typestr)
331: typedef = @decode_typemap[typename]
332: if typedef
333: return decode_definedtype(elename, typename, typedef, arytypestr)
334: end
335: end
336: return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
337: extraattr)
338: end
339:
340: if parent.type == XSD::AnyTypeName
341: return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
342: extraattr)
343: end
344:
345: # parent.definedtype == nil means the parent is SOAPUnknown. SOAPUnknown
346: # is generated by decode_tag_by_type when its type is anyType.
347: parenttype = parent.definedtype || @decode_typemap[parent.type]
348: unless parenttype
349: return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
350: extraattr)
351: end
352:
353: definedtype_name = parenttype.child_type(elename)
354: if definedtype_name and (klass = TypeMap[definedtype_name])
355: return decode_basetype(klass, elename)
356: elsif definedtype_name == XSD::AnyTypeName
357: return decode_tag_by_type(ns, elename, typestr, parent, arytypestr,
358: extraattr)
359: end
360:
361: if definedtype_name
362: typedef = @decode_typemap[definedtype_name]
363: else
364: typedef = parenttype.child_defined_complextype(elename)
365: end
366: decode_definedtype(elename, definedtype_name, typedef, arytypestr)
367: end
# File lib/soap/encodingstyle/soapHandler.rb, line 451
451: def decode_textbuf(node)
452: case node
453: when XSD::XSDHexBinary, XSD::XSDBase64Binary
454: node.set_encoded(@textbuf)
455: when XSD::XSDString
456: if @charset
457: @textbuf = XSD::Charset.encoding_from_xml(@textbuf, @charset)
458: end
459: if node.definedtype
460: node.definedtype.check_lexical_format(@textbuf)
461: end
462: node.set(@textbuf)
463: when SOAPNil
464: # Nothing to do.
465: when SOAPBasetype
466: node.set(@textbuf)
467: else
468: # Nothing to do...
469: end
470: @textbuf = ''
471: end
# File lib/soap/encodingstyle/soapHandler.rb, line 303
303: def encode_attr_value(generator, ns, qname, value)
304: if value.is_a?(SOAPType)
305: ref = SOAPReference.new(value)
306: generator.add_reftarget(qname.name, value)
307: ref.refidstr
308: else
309: value.to_s
310: end
311: end
# File lib/soap/encodingstyle/soapHandler.rb, line 257
257: def encode_attrs(generator, ns, data, parent)
258: attrs = {}
259: return attrs if data.is_a?(SOAPReference)
260:
261: if !parent || parent.encodingstyle != EncodingNamespace
262: if @generate_explicit_type
263: SOAPGenerator.assign_ns(attrs, ns, EnvelopeNamespace)
264: attrs[ns.name(AttrEncodingStyleName)] = EncodingNamespace
265: end
266: data.encodingstyle = EncodingNamespace
267: end
268:
269: if data.is_a?(SOAPNil)
270: attrs[ns.name(XSD::AttrNilName)] = XSD::NilValue
271: elsif @generate_explicit_type
272: if data.type.namespace
273: SOAPGenerator.assign_ns(attrs, ns, data.type.namespace)
274: end
275: if data.is_a?(SOAPArray)
276: if data.arytype.namespace
277: SOAPGenerator.assign_ns(attrs, ns, data.arytype.namespace)
278: end
279: SOAPGenerator.assign_ns(attrs, ns, EncodingNamespace)
280: attrs[ns.name(AttrArrayTypeName)] = ns.name(create_arytype(ns, data))
281: if data.type.name
282: attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
283: end
284: elsif parent && parent.is_a?(SOAPArray) && (parent.arytype == data.type)
285: # No need to add.
286: elsif !data.type.namespace
287: # No need to add.
288: else
289: attrs[ns.name(XSD::AttrTypeName)] = ns.name(data.type)
290: end
291: end
292:
293: data.extraattr.each do |key, value|
294: SOAPGenerator.assign_ns(attrs, ns, key.namespace)
295: attrs[ns.name(key)] = encode_attr_value(generator, ns, key, value)
296: end
297: if data.id
298: attrs['id'] = data.id
299: end
300: attrs
301: end