| | 86 | |
|---|
| | 87 | |
|---|
| | 88 | ### |
|---|
| | 89 | ## Ruby's obj <-> SOAP/OM mapping registry. |
|---|
| | 90 | # |
|---|
| | 91 | class Factory |
|---|
| | 92 | class FactoryError < Error; end |
|---|
| | 93 | |
|---|
| | 94 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 95 | raise NotImplementError.new |
|---|
| | 96 | end |
|---|
| | 97 | |
|---|
| | 98 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 99 | raise NotImplementError.new |
|---|
| | 100 | end |
|---|
| | 101 | |
|---|
| | 102 | protected |
|---|
| | 103 | |
|---|
| | 104 | def getTypeName( obj ) |
|---|
| | 105 | ret = nil |
|---|
| | 106 | begin |
|---|
| | 107 | ret = obj.instance_eval( "@typeName" ) || obj.instance_eval( "@@typeName" ) |
|---|
| | 108 | rescue NameError |
|---|
| | 109 | end |
|---|
| | 110 | ret |
|---|
| | 111 | end |
|---|
| | 112 | |
|---|
| | 113 | def getNamespace( obj ) |
|---|
| | 114 | ret = nil |
|---|
| | 115 | begin |
|---|
| | 116 | ret = obj.instance_eval( "@typeNamespace" ) || obj.instance_eval( "@@typeNamespace" ) |
|---|
| | 117 | rescue NameError |
|---|
| | 118 | end |
|---|
| | 119 | ret |
|---|
| | 120 | end |
|---|
| | 121 | |
|---|
| | 122 | def createEmptyObject( klass ) |
|---|
| | 123 | klass.module_eval <<-EOS |
|---|
| | 124 | begin |
|---|
| | 125 | alias __initialize initialize |
|---|
| | 126 | rescue NameError |
|---|
| | 127 | end |
|---|
| | 128 | def initialize; end |
|---|
| | 129 | EOS |
|---|
| | 130 | |
|---|
| | 131 | obj = klass.new |
|---|
| | 132 | |
|---|
| | 133 | klass.module_eval <<-EOS |
|---|
| | 134 | undef initialize |
|---|
| | 135 | begin |
|---|
| | 136 | alias initialize __initialize |
|---|
| | 137 | rescue NameError |
|---|
| | 138 | end |
|---|
| | 139 | EOS |
|---|
| | 140 | |
|---|
| | 141 | obj |
|---|
| | 142 | end |
|---|
| | 143 | |
|---|
| | 144 | def addWriter( klass, values ) |
|---|
| | 145 | values.each do |name, value| |
|---|
| | 146 | klass.module_eval <<-EOS |
|---|
| | 147 | begin |
|---|
| | 148 | alias __#{ name }= #{ name }= |
|---|
| | 149 | rescue NameError |
|---|
| | 150 | end |
|---|
| | 151 | def #{ name }=( var ) |
|---|
| | 152 | @#{ name } = var |
|---|
| | 153 | end |
|---|
| | 154 | EOS |
|---|
| | 155 | end |
|---|
| | 156 | end |
|---|
| | 157 | |
|---|
| | 158 | def restoreWriter( klass, values ) |
|---|
| | 159 | values.each do |name, value| |
|---|
| | 160 | klass.module_eval <<-EOS |
|---|
| | 161 | undef #{ name }= |
|---|
| | 162 | begin |
|---|
| | 163 | alias #{ name }= __#{ name }= |
|---|
| | 164 | rescue NameError |
|---|
| | 165 | end |
|---|
| | 166 | EOS |
|---|
| | 167 | end |
|---|
| | 168 | end |
|---|
| | 169 | |
|---|
| | 170 | def setInstanceVar( obj, var ) |
|---|
| | 171 | obj.instance_eval( "alias __initialize initialize; def initialize; end" ) |
|---|
| | 172 | obj.instance_eval( "undef initialize; alias initialize __initialize" ) |
|---|
| | 173 | obj |
|---|
| | 174 | end |
|---|
| | 175 | |
|---|
| | 176 | def toType( name ) |
|---|
| | 177 | capitalize( name ) |
|---|
| | 178 | end |
|---|
| | 179 | |
|---|
| | 180 | # Create NCName |
|---|
| | 181 | def toTypeName( name ) |
|---|
| | 182 | name.gsub( ':', '_' ) |
|---|
| | 183 | end |
|---|
| | 184 | |
|---|
| | 185 | def capitalize( target ) |
|---|
| | 186 | target.gsub('^([a-z])') { $1.tr!('[a-z]', '[A-Z]') } |
|---|
| | 187 | end |
|---|
| | 188 | end |
|---|
| | 189 | |
|---|
| | 190 | class BasetypeFactory_ < Factory |
|---|
| | 191 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 192 | soapKlass.new( obj ) |
|---|
| | 193 | end |
|---|
| | 194 | |
|---|
| | 195 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 196 | node.data |
|---|
| | 197 | end |
|---|
| | 198 | end |
|---|
| | 199 | |
|---|
| | 200 | class Base64Factory_ < Factory |
|---|
| | 201 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 202 | raise FactoryError.new |
|---|
| | 203 | end |
|---|
| | 204 | |
|---|
| | 205 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 206 | node.toString |
|---|
| | 207 | end |
|---|
| | 208 | end |
|---|
| | 209 | |
|---|
| | 210 | class CompoundtypeFactory_ < Factory |
|---|
| | 211 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 212 | if soapKlass == SOAP::SOAPArray |
|---|
| | 213 | # [ [1], [2] ] is converted to Array of Array, not 2-D Array. |
|---|
| | 214 | # To create M-D Array, you must call RPCUtils.ary2md. |
|---|
| | 215 | typeName = getTypeName( obj.type ) |
|---|
| | 216 | typeNamespace = getNamespace( obj.type ) || RubyTypeNamespace |
|---|
| | 217 | unless typeName |
|---|
| | 218 | typeName = XSD::AnyTypeLiteral |
|---|
| | 219 | typeNamespace = XSD::Namespace |
|---|
| | 220 | end |
|---|
| | 221 | param = SOAPArray.new( typeName ) |
|---|
| | 222 | param.typeNamespace = typeNamespace |
|---|
| | 223 | obj.each do | var | |
|---|
| | 224 | param.add( RPCUtils.obj2soap( var, map )) |
|---|
| | 225 | end |
|---|
| | 226 | param |
|---|
| | 227 | elsif soapKlass == SOAP::SOAPStruct |
|---|
| | 228 | param = SOAPStruct.new( toTypeName( obj.type.to_s )) |
|---|
| | 229 | param.typeNamespace = getNamespace( obj.type ) || RubyTypeNamespace |
|---|
| | 230 | obj.members.each do |member| |
|---|
| | 231 | param.add( member, RPCUtils.obj2soap( obj[ member ], map )) |
|---|
| | 232 | end |
|---|
| | 233 | param |
|---|
| | 234 | else |
|---|
| | 235 | nil |
|---|
| | 236 | end |
|---|
| | 237 | end |
|---|
| | 238 | |
|---|
| | 239 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 240 | if node.is_a?( SOAPArray ) |
|---|
| | 241 | obj = node.soap2array { | elem | |
|---|
| | 242 | RPCUtils.soap2obj( elem, map ) |
|---|
| | 243 | } |
|---|
| | 244 | obj.instance_eval( "@typeName = '#{ node.typeName }'; @typeNamespace = '#{ node.typeNamespace }'" ) |
|---|
| | 245 | obj |
|---|
| | 246 | elsif node.is_a?( SOAPStruct ) |
|---|
| | 247 | if node.typeEqual( XSD::Namespace, XSD::AnyTypeLiteral ) |
|---|
| | 248 | unknownObj( node, map ) |
|---|
| | 249 | else |
|---|
| | 250 | struct2obj( node, map ) |
|---|
| | 251 | end |
|---|
| | 252 | else |
|---|
| | 253 | raise FactoryError.new( "Unknown compound type: #{ node }" ) |
|---|
| | 254 | end |
|---|
| | 255 | end |
|---|
| | 256 | |
|---|
| | 257 | private |
|---|
| | 258 | |
|---|
| | 259 | def unknownObj( node, map ) |
|---|
| | 260 | klass = Object # SOAP::RPCUtils::Object |
|---|
| | 261 | Thread.critical = true |
|---|
| | 262 | addWriter( klass, node ) |
|---|
| | 263 | obj = klass.new |
|---|
| | 264 | node.each do |name, value| |
|---|
| | 265 | obj.send( name + "=", RPCUtils.soap2obj( value, map )) |
|---|
| | 266 | end |
|---|
| | 267 | restoreWriter( klass, node ) |
|---|
| | 268 | Thread.critical = false |
|---|
| | 269 | obj.typeNamespace = node.typeNamespace |
|---|
| | 270 | obj.typeName = node.typeName |
|---|
| | 271 | obj |
|---|
| | 272 | end |
|---|
| | 273 | |
|---|
| | 274 | def struct2obj( node, map ) |
|---|
| | 275 | obj = nil |
|---|
| | 276 | typeName = node.typeName || node.instance_eval( "@name" ) |
|---|
| | 277 | begin |
|---|
| | 278 | klass = self.instance_eval( toType( typeName )) |
|---|
| | 279 | if getNamespace( klass ) != node.typeNamespace |
|---|
| | 280 | raise NameError.new() |
|---|
| | 281 | elsif getTypeName( klass ) and ( getTypeName( klass ) != typeName ) |
|---|
| | 282 | raise NameError.new() |
|---|
| | 283 | end |
|---|
| | 284 | |
|---|
| | 285 | Thread.critical = true |
|---|
| | 286 | addWriter( klass, node ) |
|---|
| | 287 | obj = createEmptyObject( klass ) |
|---|
| | 288 | node.each do |name, value| |
|---|
| | 289 | obj.send( name + "=", RPCUtils.soap2obj( value, map )) |
|---|
| | 290 | end |
|---|
| | 291 | restoreWriter( klass, node ) |
|---|
| | 292 | Thread.critical = false |
|---|
| | 293 | |
|---|
| | 294 | rescue NameError |
|---|
| | 295 | klass = nil |
|---|
| | 296 | structName = toType( typeName ) |
|---|
| | 297 | if ( Struct.constants - Struct.superclass.constants ).member?( structName ) |
|---|
| | 298 | klass = Struct.const_get( structName ) |
|---|
| | 299 | if klass.members.length != node.members.length |
|---|
| | 300 | klass = Struct.new( structName, *node.members ) |
|---|
| | 301 | end |
|---|
| | 302 | else |
|---|
| | 303 | klass = Struct.new( structName, *node.members ) |
|---|
| | 304 | end |
|---|
| | 305 | obj = klass.new |
|---|
| | 306 | node.each do | name, value | |
|---|
| | 307 | obj.send( name + "=", RPCUtils.soap2obj( value, map )) |
|---|
| | 308 | end |
|---|
| | 309 | end |
|---|
| | 310 | |
|---|
| | 311 | obj |
|---|
| | 312 | end |
|---|
| | 313 | end |
|---|
| | 314 | |
|---|
| | 315 | class HashFactory_ < Factory |
|---|
| | 316 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 317 | if obj.is_a?( Hash ) |
|---|
| | 318 | param = SOAPStruct.new( "Map" ) |
|---|
| | 319 | param.typeNamespace = ApacheSOAPTypeNamespace |
|---|
| | 320 | i = 1 |
|---|
| | 321 | obj.each do | key, value | |
|---|
| | 322 | elem = SOAPStruct.new( "mapItem" ) |
|---|
| | 323 | elem.add( "key", RPCUtils.obj2soap( key, map )) |
|---|
| | 324 | elem.add( "value", RPCUtils.obj2soap( value, map )) |
|---|
| | 325 | param.add( "item#{ i }", elem ) |
|---|
| | 326 | i += 1 |
|---|
| | 327 | end |
|---|
| | 328 | param |
|---|
| | 329 | else |
|---|
| | 330 | nil |
|---|
| | 331 | end |
|---|
| | 332 | end |
|---|
| | 333 | |
|---|
| | 334 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 335 | if node.typeEqual( RubyTypeNamespace, 'Hash' ) |
|---|
| | 336 | obj = Hash.new |
|---|
| | 337 | keyArray = RPCUtils.soap2obj( node.key, map ) |
|---|
| | 338 | valueArray = RPCUtils.soap2obj( node.value, map ) |
|---|
| | 339 | while !keyArray.empty? |
|---|
| | 340 | obj[ keyArray.shift ] = valueArray.shift |
|---|
| | 341 | end |
|---|
| | 342 | obj |
|---|
| | 343 | elsif node.typeEqual( ApacheSOAPTypeNamespace, 'Map' ) |
|---|
| | 344 | obj = Hash.new |
|---|
| | 345 | node.each do | key, value | |
|---|
| | 346 | obj[ RPCUtils.soap2obj( value.key, map ) ] = |
|---|
| | 347 | RPCUtils.soap2obj( value.value, map ) |
|---|
| | 348 | end |
|---|
| | 349 | obj |
|---|
| | 350 | else |
|---|
| | 351 | raise FactoryError.new( "#{ node } is not a Hash." ) |
|---|
| | 352 | end |
|---|
| | 353 | end |
|---|
| | 354 | end |
|---|
| | 355 | |
|---|
| | 356 | class UnknownKlassFactory_ < Factory |
|---|
| | 357 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 358 | typeName = getTypeName( obj.type ) || obj.type.to_s |
|---|
| | 359 | param = SOAPStruct.new( typeName ) |
|---|
| | 360 | param.typeNamespace = getNamespace( obj.type ) || RubyCustomTypeNamespace |
|---|
| | 361 | if obj.type.ancestors.member?( Marshallable ) |
|---|
| | 362 | obj.instance_variables do |var, data| |
|---|
| | 363 | name = var.dup.sub!( /^@/, '' ) |
|---|
| | 364 | param.add( name, RPCUtils.obj2soap( data, map )) |
|---|
| | 365 | end |
|---|
| | 366 | else |
|---|
| | 367 | obj.instance_variables.each do |var| |
|---|
| | 368 | name = var.dup.sub!( /^@/, '' ) |
|---|
| | 369 | param.add( name, RPCUtils.obj2soap( obj.instance_eval( var ), map )) |
|---|
| | 370 | end |
|---|
| | 371 | end |
|---|
| | 372 | param |
|---|
| | 373 | end |
|---|
| | 374 | |
|---|
| | 375 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 376 | node |
|---|
| | 377 | end |
|---|
| | 378 | end |
|---|
| | 379 | |
|---|
| | 380 | =begin |
|---|
| | 381 | when SOAP::RPCUtils::Object |
|---|
| | 382 | typeName = obj.typeName |
|---|
| | 383 | param = SOAPStruct.new( typeName ) |
|---|
| | 384 | param.typeNamespace = obj.typeNamespace |
|---|
| | 385 | obj.instance_variables do |var, data| |
|---|
| | 386 | name = var.dup.sub!( /^@/, '' ) |
|---|
| | 387 | param.add( name, RPCUtils.obj2soap( data )) |
|---|
| | 388 | end |
|---|
| | 389 | param |
|---|
| | 390 | =end |
|---|
| | 391 | |
|---|
| | 392 | class TypedStructFactory_ < Factory |
|---|
| | 393 | def obj2soap( soapKlass, obj, info, map ) |
|---|
| | 394 | typeName = info[1] |
|---|
| | 395 | param = SOAPStruct.new( typeName ) |
|---|
| | 396 | param.typeNamespace = info[0] |
|---|
| | 397 | if obj.type.ancestors.member?( Marshallable ) |
|---|
| | 398 | obj.instance_variables do |var, data| |
|---|
| | 399 | name = var.dup.sub!( /^@/, '' ) |
|---|
| | 400 | param.add( name, RPCUtils.obj2soap( data, map )) |
|---|
| | 401 | end |
|---|
| | 402 | else |
|---|
| | 403 | obj.instance_variables.each do |var| |
|---|
| | 404 | name = var.dup.sub!( /^@/, '' ) |
|---|
| | 405 | param.add( name, RPCUtils.obj2soap( obj.instance_eval( var ), map )) |
|---|
| | 406 | end |
|---|
| | 407 | end |
|---|
| | 408 | param |
|---|
| | 409 | end |
|---|
| | 410 | |
|---|
| | 411 | def soap2obj( objKlass, node, info, map ) |
|---|
| | 412 | if ( node.typeNamespace != info[0] ) || ( node.typeName != info[1] ) |
|---|
| | 413 | raise FactoryError.new( "Type mismatch" ) |
|---|
| | 414 | end |
|---|
| | 415 | |
|---|
| | 416 | typeName = info[1] |
|---|
| | 417 | Thread.critical = true |
|---|
| | 418 | addWriter( objKlass, node ) |
|---|
| | 419 | obj = createEmptyObject( objKlass ) |
|---|
| | 420 | node.each do |name, value| |
|---|
| | 421 | obj.send( name + "=", RPCUtils.soap2obj( value, map )) |
|---|
| | 422 | end |
|---|
| | 423 | restoreWriter( objKlass, node ) |
|---|
| | 424 | Thread.critical = false |
|---|
| | 425 | |
|---|
| | 426 | obj |
|---|
| | 427 | end |
|---|
| | 428 | end |
|---|
| | 429 | |
|---|
| | 430 | class MappingRegistry |
|---|
| | 431 | class MappingError < Error; end |
|---|
| | 432 | |
|---|
| | 433 | class Mapping |
|---|
| | 434 | def initialize( mappingRegistry ) |
|---|
| | 435 | @map = [] |
|---|
| | 436 | @registry = mappingRegistry |
|---|
| | 437 | end |
|---|
| | 438 | |
|---|
| | 439 | def obj2soap( klass, obj ) |
|---|
| | 440 | @map.each do | objKlass, soapKlass, factory, info | |
|---|
| | 441 | if klass.ancestors.include?( objKlass ) |
|---|
| | 442 | ret = factory.obj2soap( soapKlass, obj, info, @registry ) |
|---|
| | 443 | return ret if ret |
|---|
| | 444 | end |
|---|
| | 445 | end |
|---|
| | 446 | nil |
|---|
| | 447 | end |
|---|
| | 448 | |
|---|
| | 449 | def soap2obj( klass, node ) |
|---|
| | 450 | @map.each do | objKlass, soapKlass, factory, info | |
|---|
| | 451 | if klass == soapKlass |
|---|
| | 452 | begin |
|---|
| | 453 | return factory.soap2obj( objKlass, node, info, @registry ) |
|---|
| | 454 | rescue Factory::FactoryError |
|---|
| | 455 | end |
|---|
| | 456 | end |
|---|
| | 457 | end |
|---|
| | 458 | raise MappingError.new( "Unknown klass: #{ klass }" ) |
|---|
| | 459 | end |
|---|
| | 460 | |
|---|
| | 461 | def init( initMapping = [] ) |
|---|
| | 462 | clear |
|---|
| | 463 | initMapping.each do | objKlass, soapKlass, factory, info | |
|---|
| | 464 | set( objKlass, soapKlass, factory, info ) |
|---|
| | 465 | end |
|---|
| | 466 | end |
|---|
| | 467 | |
|---|
| | 468 | def set( objKlass, soapKlass, factory, info ) |
|---|
| | 469 | @map << [ objKlass, soapKlass, factory, info ] |
|---|
| | 470 | end |
|---|
| | 471 | |
|---|
| | 472 | def clear |
|---|
| | 473 | @map.clear |
|---|
| | 474 | end |
|---|
| | 475 | end |
|---|
| | 476 | |
|---|
| | 477 | BasetypeFactory = BasetypeFactory_.new |
|---|
| | 478 | CompoundtypeFactory = CompoundtypeFactory_.new |
|---|
| | 479 | Base64Factory = Base64Factory_.new |
|---|
| | 480 | HashFactory = HashFactory_.new |
|---|
| | 481 | UnknownKlassFactory = UnknownKlassFactory_.new |
|---|
| | 482 | TypedStructFactory = TypedStructFactory_.new |
|---|
| | 483 | |
|---|
| | 484 | SOAPBaseMapping = [ |
|---|
| | 485 | [ ::NilClass, ::SOAP::SOAPNil, BasetypeFactory ], |
|---|
| | 486 | [ ::TrueClass, ::SOAP::SOAPBoolean, BasetypeFactory ], |
|---|
| | 487 | [ ::FalseClass, ::SOAP::SOAPBoolean, BasetypeFactory ], |
|---|
| | 488 | [ ::String, ::SOAP::SOAPString, BasetypeFactory ], |
|---|
| | 489 | [ ::Time, ::SOAP::SOAPDateTime, BasetypeFactory ], |
|---|
| | 490 | [ ::Date, ::SOAP::SOAPDateTime, BasetypeFactory ], |
|---|
| | 491 | [ ::Float, ::SOAP::SOAPFloat, BasetypeFactory ], |
|---|
| | 492 | [ ::Float, ::SOAP::SOAPDouble, BasetypeFactory ], |
|---|
| | 493 | [ ::Integer, ::SOAP::SOAPInt, BasetypeFactory ], |
|---|
| | 494 | [ ::Integer, ::SOAP::SOAPInteger, BasetypeFactory ], |
|---|
| | 495 | [ ::String, ::SOAP::SOAPBase64, Base64Factory ], |
|---|
| | 496 | [ ::Array, ::SOAP::SOAPArray, CompoundtypeFactory ], |
|---|
| | 497 | [ ::Struct, ::SOAP::SOAPStruct, CompoundtypeFactory ], |
|---|
| | 498 | ] |
|---|
| | 499 | |
|---|
| | 500 | UserMapping = [ |
|---|
| | 501 | [ ::Hash, ::SOAP::SOAPStruct, HashFactory ], |
|---|
| | 502 | ] |
|---|
| | 503 | |
|---|
| | 504 | def initialize() |
|---|
| | 505 | @userMap = Mapping.new( self ) |
|---|
| | 506 | @baseMap = Mapping.new( self ) |
|---|
| | 507 | @baseMap.init( SOAPBaseMapping ) |
|---|
| | 508 | @defaultFactory = UnknownKlassFactory |
|---|
| | 509 | end |
|---|
| | 510 | |
|---|
| | 511 | def set( objKlass, soapKlass, factory, info ) |
|---|
| | 512 | @userMap.set( objKlass, soapKlass, factory, info ) |
|---|
| | 513 | end |
|---|
| | 514 | |
|---|
| | 515 | def obj2soap( klass, obj ) |
|---|
| | 516 | @userMap.obj2soap( klass, obj ) || |
|---|
| | 517 | @baseMap.obj2soap( klass, obj ) || |
|---|
| | 518 | @defaultFactory.obj2soap( klass, obj, nil, self ) |
|---|
| | 519 | end |
|---|
| | 520 | |
|---|
| | 521 | def soap2obj( klass, node ) |
|---|
| | 522 | begin |
|---|
| | 523 | return @userMap.soap2obj( klass, node ) |
|---|
| | 524 | rescue MappingError |
|---|
| | 525 | begin |
|---|
| | 526 | return @baseMap.soap2obj( klass, node ) |
|---|
| | 527 | rescue MappingError |
|---|
| | 528 | end |
|---|
| | 529 | end |
|---|
| | 530 | |
|---|
| | 531 | @defaultFactory.soap2obj( klass, node, nil, self ) |
|---|
| | 532 | end |
|---|
| | 533 | |
|---|
| | 534 | def defaultFactory=( newFactory ) |
|---|
| | 535 | @defaultFactory = newFactory |
|---|
| | 536 | end |
|---|
| | 537 | end |
|---|
| 229 | | def obj2soap( obj ) |
|---|
| 230 | | case obj |
|---|
| 231 | | when SOAPBasetype, SOAPCompoundtype |
|---|
| 232 | | obj |
|---|
| 233 | | when NilClass |
|---|
| 234 | | SOAPNil.new |
|---|
| 235 | | when TrueClass, FalseClass |
|---|
| 236 | | SOAPBoolean.new( obj ) |
|---|
| 237 | | when String |
|---|
| 238 | | SOAPString.new( obj ) |
|---|
| 239 | | when Time, Date |
|---|
| 240 | | SOAPDateTime.new( obj ) |
|---|
| 241 | | when Float |
|---|
| 242 | | SOAPFloat.new( obj ) |
|---|
| 243 | | when Integer |
|---|
| 244 | | if (( -2147483648 <= obj ) && ( obj <= +2147483647 )) |
|---|
| 245 | | SOAPInt.new( obj ) |
|---|
| 246 | | else |
|---|
| 247 | | SOAPInteger.new( obj ) |
|---|
| 248 | | end |
|---|
| 249 | | when Array |
|---|
| 250 | | # [ [1], [2] ] is converted to Array of Array, not 2-D Array. |
|---|
| 251 | | # To create M-D Array, you must create SOAPArray manually now. |
|---|
| 252 | | typeName = getTypeName( obj ) |
|---|
| 253 | | typeNamespace = getNamespace( obj ) || RubyTypeNamespace |
|---|
| 254 | | unless typeName |
|---|
| 255 | | typeName = XSD::AnyTypeLiteral |
|---|
| 256 | | typeNamespace = XSD::Namespace |
|---|
| 257 | | end |
|---|
| 258 | | param = SOAPArray.new( typeName ) |
|---|
| 259 | | param.typeNamespace = typeNamespace |
|---|
| 260 | | obj.each do | var | |
|---|
| 261 | | param.add( obj2soap( var )) |
|---|
| 262 | | end |
|---|
| 263 | | param |
|---|
| 264 | | when Hash |
|---|
| 265 | | param = SOAPStruct.new( "Map" ) |
|---|
| 266 | | param.typeNamespace = ApacheSOAPTypeNamespace |
|---|
| 267 | | i = 1 |
|---|
| 268 | | obj.each do | key, value | |
|---|
| 269 | | elem = SOAPStruct.new( "mapItem" ) |
|---|
| 270 | | elem.add( "key", obj2soap( key )) |
|---|
| 271 | | elem.add( "value", obj2soap( value )) |
|---|
| 272 | | param.add( "item#{ i }", elem ) |
|---|
| 273 | | i += 1 |
|---|
| 274 | | end |
|---|
| 275 | | param |
|---|
| 276 | | when Struct |
|---|
| 277 | | param = SOAPStruct.new( toTypeName( obj.type.to_s )) |
|---|
| 278 | | param.typeNamespace = getNamespace( obj ) || RubyTypeNamespace |
|---|
| 279 | | obj.members.each do |member| |
|---|
| 280 | | param.add( member, obj2soap( obj[ member ] )) |
|---|
| 281 | | end |
|---|
| 282 | | param |
|---|
| 283 | | when SOAP::RPCUtils::Object |
|---|
| 284 | | typeName = obj.typeName |
|---|
| 285 | | param = SOAPStruct.new( typeName ) |
|---|
| 286 | | param.typeNamespace = obj.typeNamespace |
|---|
| 287 | | obj.instance_variables do |var, data| |
|---|
| 288 | | name = var.dup.sub!( /^@/, '' ) |
|---|
| 289 | | param.add( name, obj2soap( data )) |
|---|
| 290 | | end |
|---|
| 291 | | param |
|---|
| 292 | | else |
|---|
| 293 | | typeName = getTypeName( obj ) || obj.type.to_s |
|---|
| 294 | | param = SOAPStruct.new( typeName ) |
|---|
| 295 | | param.typeNamespace = getNamespace( obj ) || RubyCustomTypeNamespace |
|---|
| 296 | | if obj.type.ancestors.member?( Marshallable ) |
|---|
| 297 | | obj.instance_variables do |var, data| |
|---|
| 298 | | name = var.dup.sub!( /^@/, '' ) |
|---|
| 299 | | param.add( name, obj2soap( data )) |
|---|
| 300 | | end |
|---|
| 301 | | else |
|---|
| 302 | | obj.instance_variables.each do |var| |
|---|
| 303 | | name = var.dup.sub!( /^@/, '' ) |
|---|
| 304 | | param.add( name, obj2soap( obj.instance_eval( var ))) |
|---|
| 305 | | end |
|---|
| 306 | | end |
|---|
| 307 | | param |
|---|
| 308 | | end |
|---|
| 309 | | end |
|---|
| 310 | | |
|---|
| 311 | | |
|---|
| 312 | | def soap2obj( node ) |
|---|
| 313 | | case node |
|---|
| 314 | | when SOAPReference |
|---|
| | 681 | def RPCUtils.obj2soap( obj, mappingRegistry = MappingRegistry.new ) |
|---|
| | 682 | mappingRegistry ||= MappingRegistry.new |
|---|
| | 683 | if obj.is_a?( SOAPBasetype ) || obj.is_a?( SOAPCompoundtype ) |
|---|
| | 684 | return obj |
|---|
| | 685 | end |
|---|
| | 686 | return mappingRegistry.obj2soap( obj.type, obj ) |
|---|
| | 687 | end |
|---|
| | 688 | |
|---|
| | 689 | |
|---|
| | 690 | def RPCUtils.soap2obj( node, mappingRegistry = MappingRegistry.new ) |
|---|
| | 691 | mappingRegistry ||= MappingRegistry.new |
|---|
| | 692 | if node.is_a?( SOAPReference ) |
|---|
| 365 | | |
|---|
| 366 | | private |
|---|
| 367 | | |
|---|
| 368 | | def addMDAry( mdAry, ary, indices ) |
|---|
| 369 | | 0.upto( ary.size - 1 ) do | idx | |
|---|
| 370 | | if ary[ idx ].is_a?( Array ) |
|---|
| 371 | | addMDAry( mdAry, ary[ idx ], indices + [ idx ] ) |
|---|
| 372 | | else |
|---|
| 373 | | mdAry[ *( indices + [ idx ] ) ] = obj2soap( ary[ idx ] ) |
|---|
| 374 | | end |
|---|
| 375 | | end |
|---|
| 376 | | end |
|---|
| 377 | | |
|---|
| 378 | | def getTypeName( obj ) |
|---|
| 379 | | ret = nil |
|---|
| 380 | | begin |
|---|
| 381 | | ret = obj.instance_eval( "@typeName" ) || obj.instance_eval( "@@typeName" ) |
|---|
| 382 | | rescue NameError |
|---|
| 383 | | end |
|---|
| 384 | | ret |
|---|
| 385 | | end |
|---|
| 386 | | |
|---|
| 387 | | def getNamespace( obj ) |
|---|
| 388 | | ret = nil |
|---|
| 389 | | begin |
|---|
| 390 | | ret = obj.instance_eval( "@typeNamespace" ) || obj.instance_eval( "@@typeNamespace" ) |
|---|
| 391 | | rescue NameError |
|---|
| 392 | | end |
|---|
| 393 | | ret |
|---|
| 394 | | end |
|---|
| 395 | | |
|---|
| 396 | | def unknownObj( node ) |
|---|
| 397 | | klass = Object # SOAP::RPCUtils::Object |
|---|
| 398 | | Thread.critical = true |
|---|
| 399 | | addWriter( klass, node ) |
|---|
| 400 | | obj = klass.new |
|---|
| 401 | | node.each do |name, value| |
|---|
| 402 | | obj.send( name + "=", soap2obj( value )) |
|---|
| 403 | | end |
|---|
| 404 | | restoreWriter( klass, node ) |
|---|
| 405 | | Thread.critical = false |
|---|
| 406 | | obj.typeNamespace = node.typeNamespace |
|---|
| 407 | | obj.typeName = node.typeName |
|---|
| 408 | | obj |
|---|
| 409 | | end |
|---|
| 410 | | |
|---|
| 411 | | def struct2obj( node ) |
|---|
| 412 | | obj = nil |
|---|
| 413 | | typeName = node.typeName || node.instance_eval( "@name" ) |
|---|
| 414 | | begin |
|---|
| 415 | | klass = Object.const_get( toType( typeName )) |
|---|
| 416 | | if getNamespace( klass ) != node.typeNamespace |
|---|
| 417 | | raise NameError.new() |
|---|
| 418 | | elsif getTypeName( klass ) and ( getTypeName( klass ) != typeName ) |
|---|
| 419 | | raise NameError.new() |
|---|
| 420 | | end |
|---|
| 421 | | |
|---|
| 422 | | Thread.critical = true |
|---|
| 423 | | addWriter( klass, node ) |
|---|
| 424 | | obj = createEmptyObject( klass ) |
|---|
| 425 | | node.each do |name, value| |
|---|
| 426 | | obj.send( name + "=", soap2obj( value )) |
|---|
| 427 | | end |
|---|
| 428 | | restoreWriter( klass, node ) |
|---|
| 429 | | Thread.critical = false |
|---|
| 430 | | |
|---|
| 431 | | rescue NameError |
|---|
| 432 | | klass = nil |
|---|
| 433 | | structName = toType( typeName ) |
|---|
| 434 | | if ( Struct.constants - Struct.superclass.constants ).member?( structName ) |
|---|
| 435 | | klass = Struct.const_get( structName ) |
|---|
| 436 | | if klass.members.length != node.members.length |
|---|
| 437 | | klass = Struct.new( structName, *node.members ) |
|---|
| 438 | | end |
|---|
| 439 | | else |
|---|
| 440 | | klass = Struct.new( structName, *node.members ) |
|---|
| 441 | | end |
|---|
| 442 | | obj = klass.new |
|---|
| 443 | | node.each do | name, value | |
|---|
| 444 | | obj.send( name + "=", soap2obj( value )) |
|---|
| 445 | | end |
|---|
| 446 | | end |
|---|
| 447 | | |
|---|
| 448 | | obj |
|---|
| 449 | | end |
|---|
| 450 | | |
|---|
| 451 | | def createEmptyObject( klass ) |
|---|
| 452 | | klass.module_eval <<EOS |
|---|
| 453 | | begin |
|---|
| 454 | | alias __initialize initialize |
|---|
| 455 | | rescue NameError |
|---|
| 456 | | end |
|---|
| 457 | | def initialize; end |
|---|
| 458 | | EOS |
|---|
| 459 | | |
|---|
| 460 | | obj = klass.new |
|---|
| 461 | | |
|---|
| 462 | | klass.module_eval <<EOS |
|---|
| 463 | | undef initialize |
|---|
| 464 | | begin |
|---|
| 465 | | alias initialize __initialize |
|---|
| 466 | | rescue NameError |
|---|
| 467 | | end |
|---|
| 468 | | EOS |
|---|
| 469 | | obj |
|---|
| 470 | | end |
|---|
| 471 | | |
|---|
| 472 | | def addWriter( klass, values ) |
|---|
| 473 | | values.each do |name, value| |
|---|
| 474 | | klass.module_eval <<EOS |
|---|
| 475 | | begin |
|---|
| 476 | | alias __#{ name }= #{ name }= |
|---|
| 477 | | rescue NameError |
|---|
| 478 | | end |
|---|
| 479 | | def #{ name }=( var ) |
|---|
| 480 | | @#{ name } = var |
|---|
| 481 | | end |
|---|
| 482 | | EOS |
|---|
| 483 | | end |
|---|
| 484 | | end |
|---|
| 485 | | |
|---|
| 486 | | def restoreWriter( klass, values ) |
|---|
| 487 | | values.each do |name, value| |
|---|
| 488 | | klass.module_eval <<EOS |
|---|
| 489 | | undef #{ name }= |
|---|
| 490 | | begin |
|---|
| 491 | | alias #{ name }= __#{ name }= |
|---|
| 492 | | rescue NameError |
|---|
| 493 | | end |
|---|
| 494 | | EOS |
|---|
| 495 | | end |
|---|
| 496 | | end |
|---|
| 497 | | |
|---|
| 498 | | def setInstanceVar( obj, var ) |
|---|
| 499 | | obj.instance_eval( "alias __initialize initialize; def initialize; end" ) |
|---|
| 500 | | obj.instance_eval( "undef initialize; alias initialize __initialize" ) |
|---|
| 501 | | obj |
|---|
| 502 | | end |
|---|
| 503 | | |
|---|
| 504 | | def toType( name ) |
|---|
| 505 | | capitalize( name ) |
|---|
| 506 | | end |
|---|
| 507 | | |
|---|
| 508 | | # Create NCName |
|---|
| 509 | | def toTypeName( name ) |
|---|
| 510 | | name.gsub( ':', '_' ) |
|---|
| 511 | | end |
|---|
| 512 | | |
|---|
| 513 | | def capitalize( target ) |
|---|
| 514 | | target.gsub('^([a-z])') { $1.tr!('[a-z]', '[A-Z]') } |
|---|
| | 709 | class << RPCUtils |
|---|
| | 710 | private |
|---|
| | 711 | def addMDAry( mdAry, ary, indices ) |
|---|
| | 712 | 0.upto( ary.size - 1 ) do | idx | |
|---|
| | 713 | if ary[ idx ].is_a?( Array ) |
|---|
| | 714 | addMDAry( mdAry, ary[ idx ], indices + [ idx ] ) |
|---|
| | 715 | else |
|---|
| | 716 | mdAry[ *( indices + [ idx ] ) ] = RPCUtils.obj2soap( ary[ idx ] ) |
|---|
| | 717 | end |
|---|
| | 718 | end |
|---|
| | 719 | end |
|---|