MicroStrategy ONE

Use Tasks to Retrieve MicroStrategy Data in iOS

Third-party applications can access the Task Infrastructure to use MicroStrategy as a data provider. The application calls a task, retrieves the information from that task, and displays the information. MicroStrategy tasks can return results in a variety of formats, including XML, JSON, and binary data.

The code snippets described in this topic can be used as the basis for creating tasks to retrieve MicroStrategy data and use the XML or binary data that is returned to display the results.

This topic describes only the code needed to execute tasks and display the results.

Setting up the views

The system calls the viewDidLoad method of SampleViewController which logs in to the mobile server and initializes the instance variables—folderBrowser, objectViewer, and binaryViewer.

  • FolderBrowser and ObjectLoader are part of the Using Tasks sample
  • RWDDashboardView is part of the MicroStrategy Mobile framework.

The viewDidLoad method sets styles for the custom MicroStrategy table view where the results of the folder browsing task will be displayed and for the standard iOS view where information will be displayed for the object selected in the table view.

The system also determines if the device is an iPhone or an iPad and initializes the standard MicroStrategy view where report or documents execution results will be displayed. If the device is an iPhone, it creates a subview, called. This

Copy
- (void)viewDidLoad {
    //login to mobile server
    [self login];
    //initialize instance variables
    folderBrowser = [[FolderBrowser alloc] init];
    objectLoader = [[ObjectLoader alloc] init];
    binaryViewer = [[RWDDashboardView alloc] init];
    inSDKMode = YES;
    sdkFitWidth = YES;
    sdkRefresh = YES;
    //check this device is an ipad or iphone
    isIPad = [Utility isIPad];
    sdkFrame = CGRectZero;
    //set button styles (round corner)
    [SampleViewController decorateLayerBorder:self.button_GetFolder.layer color:nil];
    [SampleViewController decorateLayerBorder:self.button_GetHomeFolder.layer color:nil];
    //set tableView and informationView styles (round corner)
    [SampleViewController decorateLayerBorder:self.tableView.layer color:[UIColor grayColor]];
    [SampleViewController decorateLayerBorder:self.inforView.layer color:[UIColor grayColor]];
    //set GetFolder button's disable style
    [SampleViewController decorateButtonDisableStyle:self.button_GetFolder];
    //set selObjectIndex as -1 to show home folder 
    selObjectIndex=-1;
    [self loadFolder:selObjectIndex];
    [self refreshGetFolderButton];
    //initialize document viewer   
    report = [[MSIReportDisplayInfo alloc] init];
    report.project = loginSession.projectInfo;
    if(!isIPad){
        //add binaryNavView for iphone
        [self.view addSubview:binaryNavView];
        [self.view sendSubviewToBack:binaryNavView];
        binaryNavView.hidden = YES;
    }

The viewDidLoad method invokes the loadFolder method of SampleViewController, which in turn invokes the browseFolderWithID method of FolderBrowser. This method initiates the process of constructing and using the XML results of a folder browsing task, as described below.

Copy
-(void)loadFolder:(int)selIndex {
    NSString* folderID = nil;
    if(selIndex!=-1){
        folderID = [[itemsUnderFolder objectAtIndex:selIndex] objectID];
    }   
    @try {
        MSTRFolder* curFolder = [folderBrowser browseFolderWithID:folderID loginSession:loginSession];
        [curFolder retain];
        if(itemsUnderFolder!=nil){
            [itemsUnderFolder release];
        }
        itemsUnderFolder = [curFolder elements];
    }@catch (id ue) {
        [Utils showError:ue];
    }    
}

Executing the folder browse task and using the XML results to display the contents of a folder

The browseFolderWithID method of FolderBrowser constructs the folder browse task request object (FolderBrowseTaskRequest), initializes it, creates a task response handler (FolderBrowseTaskRspHandler), launches the task, gets the folder created as part of the task call, and returns the folder so that its contents can be displayed in the custom MicroStrategy table view.

Copy
-(MSTRFolder*)browseFolderWithID:(NSString*)folderID loginSession:(SessionCreator*)sessionCreator {
    [Utils logEntryMessage:[NSString stringWithFormat:@"folderID=%@",folderID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    // Construct the FolderBrowseTaskRequest object...
FolderBrowseTaskRequest* FolderBrowseTaskRequest alloc] init];
    // Initialize it...
    fbtr.sessionState = sessionCreator.sessionState;
    fbtr.project = sessionCreator.projectConfig;
    //Retrieve the shared folder if folderID is not provided
    fbtr.folderID = folderID;
    if (folderID==nil){
        fbtr.systemFolder =7;
    }
    fbtr.typeRestriction = OBJECT_SUBTYPE_RESTRICTIONS;
    fbtr.styleName = FOLDER_BROWSE_STYLE;
    fbtr.dereferenceShortcuts = NO;
    fbtr.includeObjectDesc = YES;
    fbtr.folderBlockBegin = 1;
    fbtr.folderBlockCount = -1;
    // Create an object to handle the task call response...
    FolderBrowseTaskRspHandler* handler = [[FolderBrowseTaskRspHandler alloc] initWithFolderName:0];
    // Specify it as the handler for this task...
    fbtr.handler = handler;
    // Launch the task...
    [fbtr start];
    // Did we fail with an error?
    if (handler.error != nil) {
        //pront error
        NSLog(@"task failed with an error %@", handler.error);
        // Mark the handler as autorelease so that we can throw its MSTRError...
        [handler autorelease];
        // Release the task outright...
        [fbtr release];
        @throw handler.error;
    }
    // Get the folder created as part of this task call...
     MSTRFolder* folder = handler.folder;
    [[folder retain] autorelease];
     // Release the handler and then the task...
    [handler release];
    [fbtr release];
    [Utils logReturnMessage:[NSString stringWithFormat:@"folderID=%@",folderID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    return folder;
}

FolderBrowseTaskRequest is provided as part of the MicroStrategy framework. FolderBrowser , which is part of the Using Tasks sample included with the Mobile SDK, provides the interface and implementation of folderBrowseTaskRspHandler. The methods in folderBrowseTaskRspHandlerinitWithFolderName, doStartElement, and doEndElement—save the folder name, create a MSTRFolder object and an array to hold the elements in the folder, and assign the array of child elements to the folder. If the folder object is successfully created, a SaxSupport object is created and it parses the XML results of the task.

Copy
@interface FolderBrowseTaskRspHandler: NSObject<NetworkResponseHandler, MSTRHandler> {
    @private
    // Fields associated with the loaded folder...
    MSTRFolder* folder;
    int _folderName;
    NSMutableArray* _elements;
    MSTRError* error;
}
 
// Initializers...
-(id)initWithFolderName:(NSInteger)folderName;
 
// Properties...
@property (nonatomic, readonly) MSTRFolder* folder;
@property (nonatomic, readonly) MSTRError* error;
@end
 
...
 
@implementation FolderBrowseTaskRspHandler
@synthesize folder, error;
 
-(id)initWithFolderName:(NSInteger)folderName {
    if (self = [super init]) {
        if (TRACE_LIFECYCLE) NSLog(@"%@.init is called", self);
 
        // Remember the folder name supplied the caller...
        _folderName = folderName;
 
        error = nil;
    }
 
    return self;
}
 
-(void):(NSString *)elementName namespaceURI:(NSString *)namespaceURI attributes:(NSDictionary *)  attributeDict level:(NSInteger)level support:(SAXSupport*)support {
 
    if([elementName isEqualToString:ERROR_INFO_TAG]){
        ErrorDetails* details = [[ErrorDetails alloc] init];
        details.statusCode = [[attributeDict objectForKey:STATUS_CODE_TAG] intValue];
        details.errorCode = [[attributeDict objectForKey:ERROR_CODE_TAG] intValue];
        details.errorMsg = [attributeDict objectForKey:ERROR_MSG_TAG];
        details.src = [attributeDict objectForKey:SRC_TAG];
        error = [[MSTRError alloc] initWithErrorDetails:details];
        [details release];
        @throw error;
    } else if([elementName isEqualToString:@"root"]) {
        // Get the attributes of the element...
        NSString* nm = [attributeDict objectForKey:@"n"];
        NSString* did = [attributeDict objectForKey:@"did"];
        NSInteger type = [[attributeDict objectForKey:@"t"] intValue];
        NSInteger subtype = [[attributeDict objectForKey:@"st"] intValue];
 
        // Create a new MSTRFolder object...
        folder = [[MSTRFolder alloc] initWithContents:nm anID:did aDesc:@"" aType:type aSubtype:subtype aNamedFolderID:_folderName isShortcut:NO];
 
        // Create an array to hold elements (children) of the folder...
        _elements = [[NSMutableArray alloc] initWithCapacity:0];
    } else if ([elementName isEqualToString:@"block"]) {
        // Get the attributes of the element...
        NSString* name = [attributeDict objectForKey:@"n"];
        NSString* dssid = [attributeDict objectForKey:@"did"];
        ObjectTypes type = (ObjectTypes) [[attributeDict objectForKey:@"t"] intValue];
        ObjectSubTypes subtype = (ObjectSubTypes) [[attributeDict objectForKey:@"st"] intValue];
        NSString* desc = [attributeDict objectForKey:@"desc"];
        NSString* abbreviation = [attributeDict objectForKey:@"ab"];
        NSString* iconPath = [attributeDict objectForKey:@"icp"];
        NSString* isShortcutStr = [attributeDict objectForKey:@"isc"];
        BOOL isShortcut = [isShortcutStr isEqualToString:@"true"];
        
        // Create the appropriate object...
        ObjectInfo* object;
        if (type == ObjectTypeFolder) {
            object = [[MSTRFolder alloc] initWithContents:name anID:dssid aDesc:desc aType:type aSubtype:subtype aNamedFolderID:0 isShortcut:isShortcut];
        } else {
            object = [[ObjectInfo alloc] initWithContents:name anID:dssid aDesc:desc aType:type aSubtype:subtype anAbbrev:abbreviation isShortcut:isShortcut iconPath:iconPath];
        }
 
        NSString* accessGranted = [attributeDict objectForKey:@"acg"];
        if ([StringUtils isNotEmpty:accessGranted]) {
            object.accessGranted = [accessGranted intValue];
        }
 
        NSString* viewMedia = [attributeDict objectForKey:@"dvm"];
        if ([StringUtils isNotEmpty:viewMedia]) {
            object.viewMedia = [viewMedia intValue];
        }
 
        // Add the child object to our folder elements array...
        [_elements addObject:object];
 
        // Release it (Store has the only reference)...
        [object release];
    }
}
 
-(void):(NSString *)elementName namespaceURI:(NSString *)namespaceURI level:(NSInteger)level support:(SAXSupport*)support{
    if ([elementName isEqualToString:@"root"]) {
        // Assign the array of child elements to the folder...
        [folder setChildren:_elements];
    }
}
 
- (void):(NSData *)data request:(id<NetworkRequest>)request {
   // Diagnostics...
    if (TRACE_TASK_CALLS) {
        NSString* stringCheck = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"Folder Browse Task Request Succeeded: Response => %@", stringCheck);
        [stringCheck release];
    }
    
    // Create a SAXSupport object to parse the results...
    SAXSupport* support = [[SAXSupport alloc] initWithData:data handler:self];
 
    // Start the parsing process...
    [support start];
 
    // Release our SAX Support instance...
    [support release];
}
 
- (void):(NSError *)_error request:(id<NetworkRequest>)request {
    if (TRACE_TASK_CALLS) {
        NSLog(@"Folder Browse Task Request Failed: %@", error);
    }
    error = (MSTRError*) _error;
    [error retain];
}

The contents of the folder (that is, the parsed XML results of the folder browsing task) will be displayed in the custom MicroStrategy view at the top of the screen.  When you click a folder, report, or document in the custom MicroStrategy view, the name, ID, and type of the object will be displayed in the information view below. When you run a report or document in a folder, it will be executed using a task and the binary results of the task execution will be used to display the report or document in a standard MicroStrategy table view, as described below.

Executing the report/document execution task and using the binary results to display the report or document

The standard MicroStrategy table view below the custom MicroStrategy folder browsing view serves two purposes. When an object is selected in the folder browsing view, the table view displays information about the selected object. When a report or document is run from the folder browsing view, the table view displays the results of the executed report or document. (For an iPhone, the report or document results use all the space on the screen.) The workflow for executing and displaying a report or document are described below.

The tableView method of SampleViewController invokes the showObjectInfo method and the showObjectBinary method.

Copy
- (void)tableView:(UITableView *)tbView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    selObjectIndex = indexPath.row;
    
    ObjectInfo* item = [itemsUnderFolder objectAtIndex:selObjectIndex];
    NSInteger objectType= [item type];
    [self refreshGetFolderButton];
    
    /*only show binary view  for report and document*/
    if(objectType==ObjectTypeDocumentDefinition || objectType==ObjectTypeReportDefinition){
        
        @try {
            //disable user interactions when render binary view
            [self view].userInteractionEnabled=NO;
            
            //show objectInfo in bottom of main view
            [self showObjectInfo:item];
            
            //show object binary
            [self showObjectBinary:item];    
        }
        @finally {
            //enable user interaction after binary view is rendered
            [self view].userInteractionEnabled=YES;
        }   
               
    }else{
        [self showObjectInfo:item];
    }
    
}

The showObjectInfo method displays information about the object selected in the folder browsing view

Copy
-(void)showObjectInfo:(ObjectInfo*)objInfo {
    [self.label_ObjectName setText:[objInfo name]];
    [self.label_ObjectID setText:[objInfo objectID]];
    [self.label_ObjectType setText:[NSString stringWithFormat:@"%d", [objInfo type]]];
    
    inforView.hidden = NO;
    inforView.alpha = 1;
    [detailView bringSubviewToFront:inforView];
}

The showObjectBinary method initiates the process of executing and displaying a report or document. It invokes the loadObjectBinary method of ObjectLoader, which loads binary data for the report or document and uses it to create a document instance using the createDataModel method. It initializes an RWDDashboardView to display the binary results of report or document execution and passes the document instance to the initWithData method to populate the binary viewer.

The view controller (SampleViewController.m in the Using Tasks sample) that is hosting the RWDDashboardView should implement the RWDDashboardDelegate protocol. Some of the callback functions provide RWDDashboardView with extra information.

Copy
-(void)showObjectBinary:(ObjectInfo*)objInfo {
    
    @try {
        //load document binary data
        RWDataServiceResult* binaryData = [objectLoader loadObjectBinary:[objInfo objectID] objectType:[objInfo type] loginSession:loginSession];
        //render data and display binary
        DSSDocumentInstance* lpDocInstance = [self createDataModel:[binaryData contentData]];
        
        [binaryViewer release];
        binaryViewer = [[RWDDashboardView alloc] init];
        if(isIPad){
            [(UIView*)binaryViewer setFrame:detailView.bounds ];
        }
               
        [ (RWDDashboardView*) binaryViewer initWithData:lpDocInstance
           dataController: (id<RWDDashboardDelegate>) self
                  baseURL: nil
            webServerType: 0
          currentLayoutID: -1
               needRender: YES ];
        
        [self setDataViewerVisibility:YES];
    }@catch (id ue) {
        [Utils showError:ue];
    }
    
}

The loadObjectBinary method invokes either the executeReport or executeDocument method, depending on the object type. These methods launch a task that executes the report or document. The message ID returned by these methods is passed to the loadBinary method, which uses it to load the binary data returned by the report or document execution task. The binary data is then converted to an RWDDataServiceResult object for display in the binary view, using the initWithLayout2 method.

Copy
@implementation ObjectLoader
 
-(RWDataServiceResult*)loadObjectBinary:(NSString*)objectID objectType:(NSInteger)objectType loginSession:(SessionCreator*)sessionCreator {
    [Utils logEntryMessage:[NSString stringWithFormat:@"objectID=%@, objectType=%d",objectID, objectType] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    //execute document/report and get message id
    NSString* messageID = nil;
    if(objectType==ObjectTypeReportDefinition){
        messageID = [self executeReport:objectID loginession:sessionCreator];
    }else if(objectType==ObjectTypeDocumentDefinition){
        messageID = [self executeDocument:objectID loginSession:sessionCreator];
    }else{
        //throw an unsupported error
        NSException* unsupportedException = [NSException
                                             exceptionWithName:@"UnsupportedException"
                                             reason:[NSString stringWithFormat:@"unsupported objectType %d", objectType]
                                             userInfo:nil];
        @throw unsupportedException;
        
    }    
    
    //load binary with msg id
    NSData* document=[self loadBinary:messageID loginSession:sessionCreator];
    
    //convert binary to RWDataServiceResult
    RWDataServiceResult* result = [[[RWDataServiceResult alloc] initWithLayout2:nil groupBy:nil data:document dataPath:nil images:nil] autorelease];
    
    [Utils logReturnMessage:[NSString stringWithFormat:@"documnetID=%@",objectID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    return result;
}
@end

The executeReport and executeDocument methods each construct an ExecuteDocumentRequest object and invoke the executeEDTaskRequest method.

Copy
-(NSString*)executeReport:(NSString*)reportID  loginSession:(SessionCreator*)sessionCreator {
    
    [Utils logEntryMessage:[NSString stringWithFormat:@"reportID=%@",reportID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    // Construct the ExecuteDocumentTaskRequest object...
    ExecuteDocumentTaskRequest* edtr = (ExecuteDocumentTaskRequest*)[[RequestFactory getRequestFactory] newRequest:EnumExecuteDocumentRequest];
    // Initialize it...
    //report
    edtr.sessionState = sessionCreator.sessionState;
    edtr.objectID = reportID;
    edtr.execFlags = DssXmlExecutionUseCache + DssXmlExecutionUpdateCache;
    
    edtr.backgroundExecution = YES;
    edtr.gridResultFlags = DssXmlResultGrid;
    edtr.project = sessionCreator.projectConfig;
    
    edtr.objType = 3;
    edtr.minimalData = YES;
    // set display mode to reseved so web can decide the right value
    edtr.reportViewMode = 0;
    edtr.reportStateID = -1;
    // special handling for report as document, pass flag
    edtr.creationFlags = 8;
    edtr.executionMode = 9;
    edtr.suppressNetworkErrorAlerts = YES;
    
    NSString* msgId = [self executeEDTaskRequest:edtr loginSession:sessionCreator];
    
    [Utils logReturnMessage:[NSString stringWithFormat:@"reportID=%@, msgID=%@",reportID, msgId] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    return msgId;
    
}
-(NSString*)executeDocument:(NSString*)docID loginSession:(SessionCreator*)sessionCreator {
    [Utils logEntryMessage:[NSString stringWithFormat:@"docID=%@",docID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    
    ExecuteDocumentTaskRequest* edtr = (ExecuteDocumentTaskRequest*)[[RequestFactory getRequestFactory] newRequest:EnumExecuteDocumentRequest];
    [edtr autorelease];
    
    // Initialize it...
    edtr.objectID = docID;
    edtr.execFlags = DssXmlDocExecutionXML + DssXmlDocExecutionUseRWDCache + DssXmlDocExecutionUpdateRWDCache + DssXmlDocExecutionFlash;
    // add background execution flag
    edtr.backgroundExecution = YES;
    edtr.minimalData = YES;
    edtr.executionMode = 9;
    edtr.suppressNetworkErrorAlerts = YES;
    
    NSString* msgId = [self executeEDTaskRequest:edtr loginSession:sessionCreator];
    
    [Utils logReturnMessage:[NSString stringWithFormat:@"docID=%@, msgID=%@",docID, msgId] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    return msgId;
}

The executeEDTaskRequest method initializes an ExecuteDocumentTaskRspHandler object and invokes the executeTaskRequest method.

Copy
-(NSString*)executeEDTaskRequest:(ExecuteDocumentTaskRequest*)edtr loginSession:(SessionCreator*)sessionCreator {
    
    [edtr retain];
    edtr.sessionState = sessionCreator.sessionState;
    edtr.project = sessionCreator.projectConfig;
    
    ExecuteDocumentTaskRspHandler* handler = [[ExecuteDocumentTaskRspHandler alloc] init];    
    edtr.handler = handler; 
    NSString* msgId = nil;
    BOOL isPrompted = NO;
    
    @try {
        [self executeTaskRequest:edtr];
        msgId = handler.messageId;
        [[msgId retain] autorelease];
        isPrompted=handler.isPrompted;
        
        [Utils logMessage:[NSString stringWithFormat:@"msgID=%@, isPrompted=%d", msgId, isPrompted] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
        
        //handle prompt report/document, throw an exception
        if(isPrompted){
            NSException* unsupportedException = [NSException
                                                 exceptionWithName:@"UnsupportedException"
                                                 reason:@"prompted document/report is unsupported"
                                                 userInfo:nil];
            @throw unsupportedException;
        }
    }
    @finally {
        [edtr release]; 
        [handler release];
    }
    
    return msgId;
}

The executeTaskRequest method invokes the TaskRequest method and assigns it a COMTaskRspHandler object as its task handler. This method launches the task to execute the report or document.

Copy
-(void)executeTaskRequest:(TaskRequest*)taskRequest {
    [taskRequest start];
    
    COMTaskRspHandler* handler=(COMTaskRspHandler*) taskRequest.handler;
    if(handler.error!=nil){
        [[handler.error retain] autorelease];
        @throw handler.error;
    }
  • ObjectLoader provides the interface and implementation for the COMTaskRspHandler object.

Copy
@interface COMTaskRspHandler: NSObject<NetworkResponseHandler, MSTRHandler> {
    @private
    MSTRError* error;
}
@property (nonatomic, retain) MSTRError* error;
@end
 
@implementation COMTaskRspHandler
 
@synthesize error;
 
//suppress warnings
-(void)doStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI attributes:(NSDictionary *)attributeDict level:(NSInteger)level support:(SAXSupport*)support{}
 
-(void)doEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI level:(NSInteger)level support:(SAXSupport*)support{}
 
-(void)onIncrementalData:(NSData*)data request:(id<NetworkRequest>)request{
    [Utils logEntryMessage:[NSString stringWithFormat:@"data=%p",data] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
}
 
- (void)onSuccess:(NSData *)data request:(id<NetworkRequest>)request {
    [error release];
    error = nil;
    
    // Diagnostics...
    if (TRACE_TASK_CALLS) {
        NSString* stringCheck = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        [Utils logMessage:[NSString stringWithFormat:@"Succeeded: Response => %@", stringCheck] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
 
        [stringCheck release]; 
    }
    
    // Create a SAXSupport object to parse the results...
    SAXSupport* support = [[SAXSupport alloc] initWithData:data handler:self];
 
    // Start the parsing process...
    [support start];
 
    // Release our SAX Support instance...
    [support release];
}
 
- (void)onFailure:(NSError *)_error request:(id<NetworkRequest>)request {
    if (TRACE_TASK_CALLS) {
        [Utils logMessage:[NSString stringWithFormat:@"Failed: error => %@ ", _error] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    }
    self.error = (MSTRError*) _error;
}
 
- (void)onProgress:(long long)loadedSize Total:(long long)totalSize request:(id<NetworkRequest>)request {
    if (TRACE_TASK_CALLS) {
        [Utils logMessage:[NSString stringWithFormat:@"onProgress"] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    }    
}
 
-(void) dealloc {
    [error release];
    [super dealloc];
}
 
@end
  • ObjectLoader also provides the interface and implementation for the  ExecuteDocumentTaskRspHandler object.

Copy
@interface ExecuteDocumentTaskRspHandler: COMTaskRspHandler {
    @private
    NSString* messageId;
    NSInteger stateID;
    NSInteger messageStatus;
    BOOL isPrompted;
}
 
@implementation ExecuteDocumentTaskRspHandler
 
@synthesize messageId;
@synthesize stateID;
@synthesize messageStatus;
@synthesize isPrompted;
 
-(void)doStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI attributes:(NSDictionary *)attributeDict level:(NSInteger)level support:(SAXSupport*)support{
    if ([elementName isEqualToString:@"msg"]) {
        self.messageId = [attributeDict valueForKey:@"id"];
        self.stateID = [[attributeDict valueForKey:@"st"] intValue];
        self.messageStatus = [[attributeDict valueForKey:@"status"] intValue];
        self.isPrompted = (messageStatus == DssXmlStatusPromptXML);
    }
}
 
-(void) dealloc {
    [messageId release];
    [super dealloc];
}
 
@end

The loadBinary method creates a RWDBinaryTaskRequest object and a RWDBinaryTaskrRspHandler object. It invokes the executeTaskRequest method. The executeTaskRequest method launches the task to convert the binary results of report/document execution so that it can be displayed in the MicroStrategy view.

Copy
-(NSData*)loadBinary:(NSString*)messageID loginSession:(SessionCreator*)sessionCreator {
    
    [Utils logEntryMessage:[NSString stringWithFormat:@"messagID=%@",messageID] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    NSString* sessionState = sessionCreator.sessionState;
    
    DevicePreferences* devicePrefs = [[[PreferencesStore preferencesStore] preferencesCopy] retain];
    ProjectConfiguration* projectConfig = sessionCreator.projectConfig;
    
    RWDBinaryTaskRequest* taskRequest = (RWDBinaryTaskRequest*)[[RequestFactory getRequestFactory] newRequest:EnumRWDBinaryRequest];
    RWDBinaryTaskRspHandler* handler = [[RWDBinaryTaskRspHandler alloc] init];
    taskRequest.handler = handler;
    taskRequest.messageID = messageID;
    taskRequest.resultFlags = DssBinaryContextFlexDefn | DssBinaryContextFlexData | DssBinaryContextFlexDrill;
    taskRequest.detailFlags = 0x80 | 0x800;
    
    if ([Generic getDeviceType] == DeviceTypeIPhone) {
        taskRequest.orientation = DssDeviceOrientationPortrait;
    }
    else {
        taskRequest.orientation = DssDeviceOrientationReserved;
    }
    
    taskRequest.sessionState = sessionState;
    taskRequest.project = projectConfig;
    taskRequest.timeout = 1000000;
    taskRequest.suppressNetworkErrorAlerts = YES;
    NSData* doc = nil;
    
    @try {
        [self executeTaskRequest:taskRequest];
        
        doc = handler.document;
        [[doc retain]autorelease];
    }
    @finally {
       [taskRequest release];
       [handler release];
       [devicePrefs release];
    }
    
    [Utils logReturnMessage:[NSString stringWithFormat:@"messagID=%@, doc=%p",messageID, doc] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
    
    return doc;
}
  • ObjectLoader provides the interface and implementation for the RWDBinaryTaskRspHandler object.

Copy
@interface RWDBinaryTaskRspHandler: COMTaskRspHandler {
    @private
    NSData* document;
}
@property (nonatomic, retain) NSData* document;
@end
 
@implementation RWDBinaryTaskRspHandler
@synthesize document;
- (void) onSuccess:(NSData *)data request:(id<NetworkRequest>)request {
    self.document=[data retain];
    // Diagnostics...
    if (TRACE_TASK_CALLS) {
        NSString* stringCheck = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        [Utils logMessage:[NSString stringWithFormat:@"Succeeded: Response => %@", stringCheck] className:NSStringFromClass([self class]) methodName:NSStringFromSelector(_cmd)];
        [stringCheck release]; 
    }    
}
 
-(void) dealloc {
    [document release];
    [super dealloc];
}
 
@end
  • ObjectLoader also provides the interface and implementation for the ExecuteDocumentTaskRspHandler object.
Copy
@interface ExecuteDocumentTaskRspHandler: COMTaskRspHandler {
    @private
    NSString* messageId;
    NSInteger stateID;
    NSInteger messageStatus;
    BOOL isPrompted;
}
 
@property (nonatomic, retain) NSString* messageId;
@property (nonatomic) NSInteger stateID;
@property (nonatomic) NSInteger messageStatus;
@property (nonatomic) BOOL isPrompted;
 
@end
 
@interface RWDBinaryTaskRspHandler: COMTaskRspHandler {
    @private
    NSData* document;
}
 
@property (nonatomic, retain) NSData* document;
@end

The createDataModel method creates a document instance and loads it with the binary data.

Copy
-(DSSDocumentInstance*)createDataModel:(NSData*)iDocData {
    DSSDocumentInstance* lpDocInstance = new DSSDocumentInstance();
    
    // set document instance binary definition limit
    DevicePreferences *dp = [[[PreferencesStore preferencesStore] masterPreferences] retain];
    ProjectInfo* lpProjectInfo = [report project];
    ProjectConfiguration* projectConfig = [[dp getProjectConfiguration:lpProjectInfo] retain];
    
    NSString* projectID = nil;
    if (projectConfig != nil) {
        projectID = projectConfig.projectID;
        
        lpDocInstance->setProjectID(((std::string)[projectID UTF8String]).c_str());
    }
    
    [projectConfig release];
    [dp release];
       
    unsigned char * lpBuffer;
    NSUInteger length;
    
    lpBuffer = (unsigned char*)[iDocData bytes];
    length = [iDocData length];
    
    lpDocInstance->LoadInstanceFromBinary(lpBuffer, length, false);
    
    return lpDocInstance;
}

The report or document results will be displayed in a standard MicroStrategy view. In the case of an iPhone, the Report Execution view will take up the whole screen; in the case of an iPad, the Report Execution view will take the place of the Information view at the bottom of the screen.