vendoo_v1.0/Pods/PicoKit/Pod/SOAP/PicoSOAPReader.m

121 lines
4.3 KiB
Objective-C

//
// PicoSOAPReader.m
// Pico
//
// Created by bulldog on 13-3-13.
// Copyright (c) 2013 LeanSoft Technology. All rights reserved.
//
#import "PicoSOAPReader.h"
#import "GDataXMLNode.h"
#import "PicoBindingSchema.h"
#import "PicoPropertySchema.h"
#import "PicoClassSchema.h"
#import "PicoConstants.h"
#import "PicoConverter.h"
#import "PicoXMLElement.h"
#import "SOAP11Envelope.h"
#import "SOAP12Envelope.h"
#import "SOAP11Body.h"
#import "SOAP12Body.h"
#import "SOAP11Fault.h"
#import "SOAP12Fault.h"
#import "PicoXMLElement.h"
@interface PicoXMLReader (Private)
-(void)read:(id)value element:(GDataXMLElement *)element;
-(void)readAnyElement:(id)value element:(GDataXMLElement *)element;
-(BOOL)readAnyElement:(id)value element:(GDataXMLElement *)element bindClass:(Class) clazz;
@end
@implementation PicoSOAPReader
static NSString *SOAP11_NS = @"http://schemas.xmlsoap.org/soap/envelope/";
static NSString *SOAP12_NS = @"http://www.w3.org/2003/05/soap-envelope";
static NSString *INNER_CLASS_KEY = @"innerClass";
// Convert binary data to object of specific class
-(id)fromData:(NSData *)data withSOAPClass:(Class)soapClazz innerClass:(Class)innerClazz {
BOOL soap11 = (soapClazz == [SOAP11Envelope class]);
BOOL soap12 = (soapClazz == [SOAP12Envelope class]);
if (!soap11 && !soap12) {
@throw [NSException exceptionWithName:@"ReaderException" reason:[NSString stringWithFormat:@"can't read non-soap class : %@", NSStringFromClass(soapClazz)] userInfo:nil];
}
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data error:&error];
if (!doc) {
@throw [NSException exceptionWithName:@"ReaderException" reason:[NSString stringWithFormat:@"fail to parse xml data , Error : %@", error] userInfo:[error userInfo]];
}
GDataXMLElement *rootElement = [doc rootElement];
PicoBindingSchema *bs = [PicoBindingSchema fromClass:soapClazz];
PicoClassSchema *cs = bs.classSchema;
NSString *xmlName = cs.xmlName;
if ([xmlName length] == 0) {
xmlName = bs.className;
}
NSString *rootName = [rootElement localName];
if (![xmlName isEqualToString: rootName]) {
@throw [NSException exceptionWithName:@"ReaderException" reason:[NSString stringWithFormat:@"root name mismatch , xml name : %@, root name : %@", xmlName, rootName] userInfo:nil];
}
// soap version check
NSString *soapNs = [rootElement URI];
if (soap11 && [soapNs isEqualToString:SOAP12_NS]) {
@throw [NSException exceptionWithName:@"ReaderException" reason:@"Expecting SOAP 1.1 response, but got SOAP 1.2 response" userInfo:nil];
} else if (soap12 && [soapNs isEqualToString:SOAP11_NS]) {
@throw [NSException exceptionWithName:@"ReaderException" reason:@"Expecting SOAP 1.2 response, but got SOAP 1.1 response" userInfo:nil];
}
NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
threadDictionary[INNER_CLASS_KEY] = innerClazz;
id obj = [soapClazz new];
[super read: obj element: rootElement];
return obj;
}
-(void)readAnyElement:(id)value element:(GDataXMLElement *)element {
PicoBindingSchema *bs = [PicoBindingSchema fromObject:value];
PicoPropertySchema *anyPs = bs.anyElementSchema;
if (!anyPs) return;
BOOL soap11 = [value isMemberOfClass:[SOAP11Body class]];
BOOL soap12 = [value isMemberOfClass:[SOAP12Body class]];
if (soap11 || soap12) {
NSMutableDictionary *threadDictionary = [[NSThread currentThread] threadDictionary];
Class innerClazz = threadDictionary[INNER_CLASS_KEY];
BOOL success = [super readAnyElement:value element:element bindClass:innerClazz];
if (!success) {
Class faultClass = soap11? [SOAP11Fault class] : [SOAP12Fault class];
[super readAnyElement:value element:element bindClass:faultClass];
}
} else {
[super readAnyElement:value element:element];
}
}
-(id)fromString:(NSString *)string withSOAPClass:(Class)clazz innerClass:(Class)innerClazz {
NSData *data = [string dataUsingEncoding: CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)self.config.encoding)) allowLossyConversion:NO];
return [self fromData:data withSOAPClass:clazz innerClass:innerClazz];
}
@end