Description: creating a line chart that uses cube as a data source.
#import "Charting.h" #import "DataSource.h" #import <UIKit/UIKit.h> #include "GridTotalsSettingsHelper.h" #include "PPLMetabase.h" #include "PPLOlapReportPlistKeys.h" #include "PPLPivotTableConditionFilterFactory.h" @interface ViewController : UIViewController<ChartTouchesDelegate> { Chart *chart; float max; float min; LineSeries *currSeries; NSMutableDictionary *m_numberFormat; SPPLMetabase m_metabase; SPPLMetabaseRepositoryObjectDescriptor m_reportDescriptor; DataSource *dataSource; SPPLPivotTable m_gridPivotTable; SPPLPivot m_gridPivot; SPPLOlapReport m_olapReport; } // Executes custom example placed in the body of this method - (void) executeExample; - (ChartLabel *)createDefaultLabel; @end
#import "ViewController.h" #include "NArray.h" #include "NNotificationCenterExt.h" #include "PPLAccessRightsManager.h" #include "PPLCalendarDimension.h" #include "PPLCalendarDimensionDataLevel.h" #include "PPLCalendarDimensionDataLevels.h" #include "PPLCalendarPeriodDimension.h" #include "PPLCubeDataSource.h" #include "PPLCubeTableField.h" #include "PPLDashboardReport.h" #include "PPLMetabase.h" #include "PPLMetabasePool.h" #include "PPLMetabaseRepositoryWarehousePool.h" #include "PPLOlapReport.h" #include "PPLPivotTableCalculatedHeaderElement.h" #include "PPLPivotTableCalculator.h" #include "PPLPivotTableCalculatorMutableSetting.h" #include "PPLPivotTableConditionFilter.h" #include "PPLPivotTableFilterElements.h" #include "PPLPivotTableHeaderElement.h" #include "PPLPivotTableHeaderElements.h" @interface ViewController() @property (retain) UIAlertView* waiterView; @property (assign) int signingAttempsCount; @end @implementation ViewController const int static delay = 3; const int maxSigningAttempsCount = 3; // Number of repository connection attempts NSString *host = @"nrspo-121.prognozcloud.ru"; NSString *webAppName = @"r7.2"; NSString *mobileAppName = @"mobile"; NSString *login = @"sa"; NSString *password = @"sa"; -(id)init { self = [super init]; if (self) { [self setSigningAttempsCount: 0]; // Set successful report download event handler NNotificationCenterExt::addObserver(self, @selector(repositoryDownloadingFinished:), didDownloadRepositoryDescriptorNotificationName, NULL); // Set unsuccessful report download event handler NNotificationCenterExt::addObserver(self, @selector(repositoryDownloadingFailed:), didFailDownloadingRepositoryDescriptorNotificationName, NULL); // Set authentication complete event handler NNotificationCenterExt::addObserver(self, @selector(authenticationCompleted:), didAuthenticationCompletedDescriptorNotificationName, NULL); [self showWaiterWithText: NSLocalizedString(@"Signing in...", nil)]; // Connect repository [self connect]; } return self; } -(void) connect { // Create a metabase containing information on reports m_metabase = PPLMetabase::sharedMetabase(NString::stringWithNSString(host), NString::stringWithNSString(webAppName), NString::stringWithNSString(mobileAppName)); if (m_metabase->getHost() == nil) { m_metabase->setHost(NString::stringWithNSString(host)); } if (m_metabase->isHttpsEnabled()) { m_metabase->setHttpsEnabled(false); } [self updateRepository]; // Authenticate user [self authenticateUser]; } // Authenticates user -(void)authenticateUser { /* Set login and password for checking if specified user can access reports */ PPLAccessRightsManager::accessRightsManager()->setAuthenticatedUser(m_metabase->getLogin(), m_metabase->getPassword()); } // Refreshes repository state based on remote server data -(void)updateRepository { m_metabase->updateRemoteRepositoryContent(NString::stringWithNSString(login), NString::stringWithNSString(password)); } - (void)authenticationCompleted:(NNotification *)notification { SNNumber errorType = notification->userInfo()->objectForKey<NNumber>(errorNotificationTypeKey); if (errorType->intValue() != PPLMetabase::errSuccess) { _signingAttempsCount++; NSLog(@"Authorization error (attempt %d)", _signingAttempsCount); if (_signingAttempsCount < maxSigningAttempsCount) { [self connect]; } else { [self hideWaiter]; } } } - (void)repositoryDownloadingFinished:(NNotification *)notification { NSLog(@"Repository data is successfully obtained"); [self hideWaiter]; [self initObjectDescriptor]; } - (void)repositoryDownloadingFailed:(NNotification *)notification { NSLog(@"Error loading repository data"); } // Initializes repository object -(void)initObjectDescriptor { N_FOREACH(SPPLMetabaseRepositoryDescriptor, repositoryDescriptor, [self getRepositories]) { // Set repository as the current one [self setCurrentRepository: repositoryDescriptor]; // Get express report SPPLMetabaseRepositoryObjectDescriptor olapObjectDescriptor = [self getObjectDescriptorWithType: PPLMetabaseRepositoryObjectDescriptor::kExpressAnalysisReport]; // Delete this report if ([self removeRepositoryObject: olapObjectDescriptor]) { return; }; // Load repository object description bool isDownloading = [self downloadRepositoryObject: olapObjectDescriptor]; if (isDownloading) { return; } } } // Sets current repository -(void)setCurrentRepository: (SPPLMetabaseRepositoryDescriptor) repositoryDescriptor { m_metabase = PPLMetabase::sharedMetabase(repositoryDescriptor); } // Returns array of repositories -(SNArray) getRepositories { SPPLMetabaseRepositoryWarehouse defaultWarehouse = PPLMetabaseRepositoryWarehousePool::sharedWarehousePool()->defaultWarehouse(); return defaultWarehouse->repositoriesList(); } // Returns description of specified type of repository object -(SPPLMetabaseRepositoryObjectDescriptor) getObjectDescriptorWithType: (PPLMetabaseRepositoryObjectDescriptor::Type) type { SPPLMetabaseRepositoryObjectDescriptor result = NULL; N_FOREACH(SPPLMetabaseRepositoryObjectDescriptor, objectDescriptor, m_metabase->allReportDescriptors()) { if(objectDescriptor->isReport()) { if(objectDescriptor->type() == type) { result = objectDescriptor; break; } } } return result; } // Removes specified repository object -(bool)removeRepositoryObject: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor { if (objectDescriptor && objectDescriptor->isLocal()) { [self removeReport: objectDescriptor]; NSLog(@"Repository object is removed"); return true; } else { return false; } } // Loads specified repository object -(bool)downloadRepositoryObject: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor { if (objectDescriptor && objectDescriptor->isRemote()) { [self downloadReport: objectDescriptor]; return true; } else { return false; } } -(void) downloadReport: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor { [self addObjectDownloadObservers]; m_reportDescriptor = objectDescriptor; // Create a repository pool SPPLMetabasePool metabasePool = PPLMetabasePool::sharedMetabasePool(); SPPLMetabase metabase = metabasePool->sharedMetabase(NString::stringWithNSString(host), NString::stringWithNSString(webAppName), NString::stringWithNSString(mobileAppName)); metabase->downloadReport(m_reportDescriptor); [self showWaiterWithText:NSLocalizedString(@"Downloading", nil)]; } - (void)reportDownloadingFinished:(NNotification *)notification { SNDictionary userInfo = notification->userInfo(); SNNumber isLastInQueue = userInfo->objectForKey<NNumber>(PPLNetDownloadManager::IS_LAST_IN_QUEUE_KEY); if (isLastInQueue && isLastInQueue->boolValue()) { [self initReport]; } } - (void)reportDownloadingFailed:(NNotification *)notification { [self removeObjectDownloadObservers]; } - (void)downloadProgressNotification:(NNotification *)notification { NSLog(@"%@",notification->userInfo()->description()->nsString()); } - (void)initReport { if (m_reportDescriptor->isLocal()) { NSLog(@"Report is successfully loaded"); [self hideWaiter]; [self showWaiterWithText: NSLocalizedString(@"Opening...", nil)]; [self removeObjectDownloadObservers]; // Open report [self openReport]; } } -(void)addObjectDownloadObservers { NNotificationCenterExt::addObserver(self, @selector(downloadProgressNotification:), downloadProgressNotificationName, NULL); NNotificationCenterExt::addObserver(self, @selector(reportDownloadingFinished:), downloadFinishedNotificationName, NULL); NNotificationCenterExt::addObserver(self, @selector(reportDownloadingFailed:), downloadFailedNotificationName, NULL); } -(void)removeObjectDownloadObservers { NNotificationCenterExt::removeObserver(self, downloadProgressNotificationName, NULL); NNotificationCenterExt::removeObserver(self, downloadFailedNotificationName, NULL); NNotificationCenterExt::removeObserver(self, downloadFinishedNotificationName, NULL); } // Displays Displays busy indicator - (void)showWaiterWithText: (NSString *) text { self.waiterView = [[[UIAlertView alloc] initWithTitle:text message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil] autorelease]; UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]; activityView.frame = CGRectMake(139.0f - 18.0f, 50.0f, 37.0f, 37.0f); [activityView startAnimating]; [[self waiterView] addSubview:activityView]; [[self waiterView] show]; [activityView release]; } // Remove busy indicator - (void)hideWaiter { [[self waiterView] dismissWithClickedButtonIndex:0 animated:NO]; [self setWaiterView: nil]; } // Removes specified repository object -(void)removeReport: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor { NSString *slash = @"/"; NSMutableString *repositoryPath = (m_metabase->isHttpsEnabled())?[NSMutableString stringWithString:@"https://"]: [NSMutableString stringWithString:@"http://"]; [repositoryPath appendString: host]; [repositoryPath appendString: slash]; [repositoryPath appendString: webAppName]; [repositoryPath appendString: slash]; [repositoryPath appendString: mobileAppName]; SPPLMetabase metabase = PPLMetabase::sharedMetabase(NString::stringWithNSString(repositoryPath)); metabase->removeObject(objectDescriptor); // Update repository state [self updateRepository]; } -(void) openReport { SPPLMetabase metabase = PPLMetabase::sharedMetabase(m_reportDescriptor->repositoryDescriptor()); m_olapReport = metabase->getReportByObjectKey(m_reportDescriptor->key())->qClass<PPLOlapReport>(); SNDictionary gridOlapPlist = m_olapReport->storageDictionary()->objectForKey<NDictionary>(GRID_OLAP_KEY); SPPLOlapReport gridOlapReport = NULL; if (gridOlapPlist != NULL) { gridOlapReport = PPLOlapReport::olapReport(m_olapReport->descriptor(), gridOlapPlist); } m_gridPivot = (gridOlapReport != NULL) ? PPLPivot::pivot(gridOlapReport) : PPLPivot::pivot(m_olapReport); m_gridPivotTable = PPLPivotTable::pivotTable(m_gridPivot); int64 key; if (SNArray fixed = m_olapReport->fixedDimensions()) { for (int i = 0, nCount = fixed->count(); i < nCount; ++i) { SPPLDimension dim = fixed->objectAtIndex<PPLDimension>(i); key = dim->key(); m_gridPivot->selectionSet()->getSelectionByDimensionKey(key)->selectAll(); } } SNDictionary gridPivotTablePlist = m_olapReport->storageDictionary()->objectForKey<NDictionary>(GRID_PIVOT_TABLE_KEY); if (gridPivotTablePlist != NULL) { m_gridPivotTable->setupFromPlist(gridPivotTablePlist); } else { [self applyGridSettings]; } m_gridPivot->refresh(); NNotificationCenterExt::addObserver(self, @selector(pivotDidUpdateNotificatonHandler:), didUpdatePivotDataNotificationName, m_gridPivot); [self hideWaiter]; // Execute custom example [self performSelector:@selector(executeExample) withObject:NULL afterDelay:delay]; } -(void) pivotDidUpdateNotificatonHandler: (NNotification *) notification { dataSource = [[DataSource alloc] initWithPivotTable:m_gridPivotTable]; [self createChart]; } -(void) createChart { m_numberFormat = [[NSMutableDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], @"asInSource", [NSNumber numberWithInt:2], @"decNumbers", [NSNumber numberWithBool:YES], @"separator", @"", @"prefix", @"", @"prefix", [NSNumber numberWithBool:NO], @"negativeRed", nil] retain]; // Create a chart and determine its size chart = [[Chart alloc] initWithName:@"chart"]; chart.frame = CGRectMake(0, 0, 450, 450); // Set grey color border [[chart layer] setBorderColor: [[UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1] CGColor]]; [[chart layer] setBorderWidth: 1.0f]; chart.backgroundColor = [UIColor whiteColor]; ValueAxis *ax = [chart.axes objectForKey:[NSNumber numberWithInt:AxisLineX]]; ax.axisLabelsVertical = NO; // Create a data source // Create the first series LineSeries *series = [LineSeries new]; series.dataIndex = 0; // Series index, numbering starts with zero series.defaultLabel = [self createDefaultLabel]; [series setColor:[UIColor blueColor]]; // Series line color series.isLegendVisible = YES; // Display in legend [series setShadowColor:[UIColor blueColor]]; // Shadow color series.shadowOpacity = 0.2;// Shadow transparency series.shadowRadius = 0.01;// Shadow radius series.showShadow = YES; // Display shadow // Create the second series LineSeries *series1 = [LineSeries new]; series1.dataIndex = 1; series1.defaultLabel = [self createDefaultLabel]; [series1 setColor:[UIColor redColor]]; series1.isLegendVisible = YES; [series1 setShadowColor:[UIColor redColor]]; series1.shadowOpacity = 0.2; series1.shadowRadius = 0.01; series1.showShadow = YES; // Create the third series LineSeries *series2 = [LineSeries new]; series2.dataIndex = 2; series2.defaultLabel = [self createDefaultLabel]; [series2 setColor:[UIColor greenColor]]; series2.isLegendVisible = YES; [series2 setShadowColor:[UIColor greenColor]]; series2.shadowOpacity = 0.2; series2.shadowRadius = 0.01; series2.showShadow = YES; // Create the fourth series LineSeries *series3 = [LineSeries new]; series3.dataIndex = 3; series3.defaultLabel = [self createDefaultLabel]; [series3 setColor:[UIColor darkGrayColor]]; series3.isLegendVisible = YES; [series3 setShadowColor:[UIColor darkGrayColor]]; series3.shadowOpacity = 0.2; series3.shadowRadius = 0.01; series3.showShadow = YES; // Set data source [chart setDataSource:dataSource]; [chart setDelegate:self]; // Get maximum and minimum values of Y axis scale [dataSource prepare]; // Add created series to chart [chart addSeries:series]; [chart addSeries:series1]; [chart addSeries:series2]; [chart addSeries:series3]; // Hide timeline [[chart timeAxis] setVisible:NO]; // Update data [chart forceDataUpdate]; // Display chart [self.view addSubview:chart]; // Calculate size for chart drawing min = dataSource.yMin; max = dataSource.yMax; } - (void)viewDidLoad { [super viewDidLoad]; // Determine link to selected series currSeries = nil; } // Returns all data dimensions - (SNArray)allDimensions { SNMutableArray allDimensions = NMutableArray::mutableArrayWithArray(m_gridPivot->topHeader()->dimensions()); allDimensions->addObjectsFromArray(m_gridPivot->leftHeader()->dimensions()); allDimensions->addObjectsFromArray(m_gridPivot->fixedHeader()->dimensions()); return allDimensions; } // Handle chart area touch event - (void)chartTouchesTapInView:(UIView *)v withPoint:(CGPoint)point { } // Create point labels - (ChartLabel *)createDefaultLabel { ChartLabel *result = [[[ChartLabel alloc] initWithFrame:CGRectZero] autorelease]; result.background = [[SolidColorBrush new] autorelease]; // Background result.borderColor = [UIColor blackColor]; // Border color result.borderThickness = 1; // Border width result.borderRadius = 10; // Corner rounding radius result.font = [UIFont fontWithName:@"Arial" size:18]; // Font result.formatter = [NSNumberFormatter new]; result.textAlignment = AlignmentCenter; // Text alignment result.textColor = [UIColor blackColor]; // Text color // Determine text formatting mask result.mask = [NSString stringWithFormat:@"%@#FVAL%@", (NSString *)[m_numberFormat objectForKey:@"prefix"], (NSString *)[m_numberFormat objectForKey:@"suffix"]]; result.countOfDecimalNumbers = 3; // Number of displayed decimal places result.displayNegativesInRed = NO; // Format of displaying negative values // Hide additional lines result.hasHorizontalNoteLine = result.hasVerticalNoteLine = result.hasFootNoteLine = NO; // Set minimum width result.minWidth = 0; return result; } // Applies table settings - (void)applyGridSettings { NSDictionary *settings = [self gridSettings]; if (settings != nil) { NSDictionary *dataSettings = [settings objectForKey:@"data"]; if (dataSettings != nil) { int aggregateData = [(NSNumber *)[dataSettings objectForKey:@"aggregateFixed"] intValue]; // Get data source SPPLDataSource gridDS = m_metabase->getDataSourceByObjectId(m_reportDescriptor->dataSourceRefId()); gridDS->setIsAggregate(aggregateData); } NSDictionary *totalsSettings = [settings objectForKey:@"totals"]; if (totalsSettings != nil) { BOOL emptyAsZero = [(NSString *)[totalsSettings objectForKey:@"emptyValuesAsZero"] isEqualToString:@"true"]; BOOL includeOwner = [(NSString *)[totalsSettings objectForKey:@"includeOwner"] isEqualToString:@"true"]; BOOL useHierarchy = [(NSString *)[totalsSettings objectForKey:@"hierarchyTotals"] isEqualToString:@"true"]; BOOL useLevels = [(NSString *)[totalsSettings objectForKey:@"levelTotals"] isEqualToString:@"true"]; SPPLPivotTableTotalsSettings settings = m_gridPivotTable->totalsSettings(); settings->setTreatEmptyAsZero(emptyAsZero); settings->setIncludeParents(includeOwner); settings->setUseHierarchy(useHierarchy); settings->setUseLevels(useLevels); if (NSArray *rows = [totalsSettings objectForKey:@"rows"]) ReadPPLPivotTableTotalsTypes(settings->rowTypes(), rows); if (NSArray *columns = [totalsSettings objectForKey:@"columns"]) ReadPPLPivotTableTotalsTypes(settings->columnTypes(), columns); } NSDictionary *filterSettings = [settings objectForKey:@"gridFilter"]; if (filterSettings != nil && [[filterSettings objectForKey:@"enabled"] isEqual:@"true"]) { NSString *filterZero = [filterSettings objectForKey:@"filterZero"]; NSString *filterEmpty = [filterSettings objectForKey:@"filterEmpty"]; NSString *filterNonNumeric = [filterSettings objectForKey:@"filterNonNumeric"]; if (filterZero) { m_gridPivotTable->filterSettings()->globalSettings()->setSuppressZero([filterZero boolValue]); } if (filterEmpty) { m_gridPivotTable->filterSettings()->globalSettings()->setSuppressEmpty([filterEmpty boolValue]); } if (filterNonNumeric) { m_gridPivotTable->filterSettings()->globalSettings()->setSuppressNonNumeric([filterNonNumeric boolValue]); } int elements = [[filterSettings objectForKey:@"filterElements"] intValue]; switch (elements) { case 0: m_gridPivotTable->filterSettings()->globalSettings()->setElements(PPLPivotTableFilterElements::kRowsAndColumns); break; case 1: m_gridPivotTable->filterSettings()->globalSettings()->setElements(PPLPivotTableFilterElements::kRows); break; case 2: m_gridPivotTable->filterSettings()->globalSettings()->setElements(PPLPivotTableFilterElements::kColumns); break; } BOOL useConditions = [[filterSettings objectForKey:@"filterUseCondition"] isEqual:@"true"]; m_gridPivotTable->filterSettings()->setUseConditionFilters(useConditions); int conditionType = [[filterSettings objectForKey:@"filterCondition"] intValue]; SPPLPivotTableConditionFilterFactory filterFactory = new PPLPivotTableConditionFilterFactory(); switch (conditionType) { case 0: m_gridPivotTable->filterSettings()->setUseConditionFilters(false); break; case 1: filterFactory->setFilterType(PPLPivotTableFilterType::kEquals); break; case 2: filterFactory->setFilterType(PPLPivotTableFilterType::kNotEquals); break; case 3: filterFactory->setFilterType(PPLPivotTableFilterType::kGreater); break; case 4: filterFactory->setFilterType(PPLPivotTableFilterType::kLess); break; case 5: filterFactory->setFilterType(PPLPivotTableFilterType::kGreaterOrEquals); break; case 6: filterFactory->setFilterType(PPLPivotTableFilterType::kLessOrEquals); break; case 7: filterFactory->setFilterType(PPLPivotTableFilterType::kBetween); break; case 8: filterFactory->setFilterType(PPLPivotTableFilterType::kLessOrGreater); break; } filterFactory->setValueA(NNumber::numberWithDouble([(NSNumber *)[filterSettings objectForKey:@"filterConditionA"] doubleValue])); filterFactory->setValueB(NNumber::numberWithDouble([(NSNumber *)[filterSettings objectForKey:@"filterConditionB"] doubleValue])); filterFactory->setKeepParent(false); filterFactory->setPercentMode(false); filterFactory->setRelatedTableElement(NULL); SPPLPivotTableConditionFilterSettings settings = filterFactory->create(); m_gridPivotTable->filterSettings()->globalSettings()->setGlobalConditionalFilterSettings(settings); } NSDictionary *sortSettings = [settings objectForKey:@"gridSort"]; if (sortSettings != nil) { NSArray *columnsSortSettings = [sortSettings objectForKey:@"columns"]; if (columnsSortSettings != nil && columnsSortSettings.count > 0) { NSDictionary *columnSortSettings = [columnsSortSettings lastObject]; NSInteger columnIndex = [[columnSortSettings objectForKey:@"index"] integerValue]; NSInteger direction = [[columnSortSettings objectForKey:@"direction"] integerValue]; if (direction > 0 && m_gridPivotTable->topHeader()->elements()->elementsCount() > columnIndex) { SPPLPivotTableHeaderElement element = m_gridPivotTable->topHeader()->elements()->getElementByIndex(columnIndex); m_gridPivotTable->sorterSettings()->setRelatedTableElement(element); if (direction == 1) { m_gridPivotTable->sorterSettings()->setDirection(PPLPivotTableSortDirection::kAsc); } else if (direction == 2) { m_gridPivotTable->sorterSettings()->setDirection(PPLPivotTableSortDirection::kDesc); } } } NSArray *rowsSortSettings = [sortSettings objectForKey:@"rows"]; if (rowsSortSettings != nil && rowsSortSettings.count > 0) { NSDictionary *rowSortSettings = [rowsSortSettings lastObject]; NSInteger rowIndex = [[rowSortSettings objectForKey:@"index"] integerValue]; NSInteger direction = [[rowSortSettings objectForKey:@"direction"] integerValue]; if (direction > 0 && m_gridPivotTable->leftHeader()->elements()->elementsCount() > rowIndex) { SPPLPivotTableHeaderElement element = m_gridPivotTable->leftHeader()->elements()->getElementByIndex(rowIndex); m_gridPivotTable->sorterSettings()->setRelatedTableElement(element); if (direction == 1) { m_gridPivotTable->sorterSettings()->setDirection(PPLPivotTableSortDirection::kAsc); } else if (direction == 2) { m_gridPivotTable->sorterSettings()->setDirection(PPLPivotTableSortDirection::kDesc); } } } } } } // Returns express report table settings - (NSDictionary *)gridSettings { // Create a repository object SPPLMetabaseObject metabaseObject = new PPLMetabaseObject(m_reportDescriptor); // Create an express report object SPPLOlapReport olapObject = PPLOlapReport::olapReport(metabaseObject->descriptor()); if (olapObject->gridSettings() != NULL) { // Returns expres report table settings return (NSDictionary *)olapObject->gridSettings()->nsObject(); } else { return nil; } } // Executes custom example placed in the body of this method -(void)executeExample { } @end
See also: