Экспресс-отчёт

Описание: создание экспресс-отчёта, использующего куб в качестве источника данных.

Файл «ViewController.h»

#import <UIKit/UIKit.h>
#include "PPLMetabase.h"
#include "PPLMetabaseRepositoryObjectDescriptor.h"
#import "MABaseReportViewController.h"
#include "PPLOlapReport.h"
@interface ViewController : UIViewController <MATreeMap3DViewControllerDelegate> {
    SPPLMetabaseRepositoryObjectDescriptor m_olapReportDescriptor;
    SPPLOlapReport m_olapReport;
    MABaseReportViewController* m_controller;
    SPPLMetabase m_metabase;
}
- (void) executeExample;
@end

Файл «ViewController.mm»

#import "BubbleDataViewDatasource.h"
#import "ChartDataViewDatasource.h"
#import "ChartRowViewController.h"
#import "ChartTypeSelectorViewController.h"
#import "FontSizeViewController.h"
#import "GridDataViewDatasource.h"
#import "MABaseReportViewController.h"
#import "MABubbleDataViewController.h"
#import "MAElementDataSourceRoleSelectorViewController.h"
#import "MAElementDataSourceRoleSelectorViewController_BubbleTree.h"
#import "MAElementDataSourceRoleSelectorViewController_TreeMap.h"
#import "MAExpressAnalysisReportViewController.h"
#import "MAExpressAnalysisReportViewControllerFactory.h"
#import "MAGridDataSourcePersistentKey.h"
#import "MAGridDelegate.h"
#import "MAMapData2DViewController.h"
#import "MapDataViewDatasource.h"
#import "MAProceduralReportViewControllerFactory.h"
#import "MobileAnalysis/ChartingColorByMetric.h"
#import "MobileAnalysis/ChartingColorIndicator.h"
#import "MobileAnalysis/ChartingSize.h"
#import "MobileAnalysis/MAChartDataViewController.h"
#import "NuGridCellWithSparkline.h"
#import "TreeMapDataViewDataSource.h"
#import "TrendLine.h"
#import "UIColor+Name.h"
#import "UIFont+Name.h"
#import "ViewController.h"
#import <MobileAnalysis/ChartRowsViewController.h>
#import <MobileAnalysis/ChartRowViewController.h>
#import <MobileAnalysis/ChartTypeSelectorViewController.h>
#import <MobileAnalysis/FontSizeViewController.h>
#import <MobileAnalysis/GridStyleKeys.h>
#import <MobileAnalysis/MABubbleTreeDataViewController.h>
#import <MobileAnalysis/MAConditionalFormattingHelper.h>
#import <MobileAnalysis/MAConditionalFormattingPoolKey.h>
#import <MobileAnalysis/MAConditionalFormattingRule.h>
#import <MobileAnalysis/MAConditionalFormattingRuleGlobalHelper.h>
#import <MobileAnalysis/MAConditionalFormattingRuleLocalHelper.h>
#import <MobileAnalysis/MAConditionalFormattingRules.h>
#import <MobileAnalysis/MAConditionalFormattingRulesGlobalHelper.h>
#import <MobileAnalysis/MAConditionalFormattingRulesLocalHelper.h>
#import <MobileAnalysis/MAConditionalFormattingScaleGlobalHelper.h>
#import <MobileAnalysis/MAConditionalFormattingScaleLocalHelper.h>
#import <MobileAnalysis/MADataReportActionViewController.h>
#import <MobileAnalysis/MADataReportSettingsViewController.h>
#import <MobileAnalysis/MADataViewDatasourceTitleUtils.h>
#import <MobileAnalysis/MADimensionElementsTableViewController.h>
#import <MobileAnalysis/MADimensionsPanelDimensionDescriptor.h>
#import <MobileAnalysis/MADimensionsPanelDimensionElementDescriptor.h>
#import <MobileAnalysis/MADimensionsPanelRoleSelectorViewController.h>
#import <MobileAnalysis/MADimensionsPanelTableViewController.h>
#import <MobileAnalysis/MADimensionsPanelTableViewDataSource.h>
#import <MobileAnalysis/MADimensionsPanelTableViewDelegate.h>
#import <MobileAnalysis/MAGlobalGridGroupsResponder.h>
#import <MobileAnalysis/MAGlobalGridRulesResponder.h>
#import <MobileAnalysis/MAGlobalGridSettingsHelper.h>
#import <MobileAnalysis/MAGridCellStyle.h>
#import <MobileAnalysis/MAGridDataSourcePersistentKey.h>
#import <MobileAnalysis/MAGridDataViewController.h>
#import <MobileAnalysis/MAGridProxyDataSource.h>
#import <MobileAnalysis/MALocalGridGroupsResponder.h>
#import <MobileAnalysis/MAMapData3DViewController.h>
#import <MobileAnalysis/MAMapDataBubbleViewController.h>
#import <MobileAnalysis/MAMapDataViewContainerController.h>
#import <MobileAnalysis/MapChart2D.h>
#import <MobileAnalysis/MATreeMap3DViewController.h>
#import <MobileAnalysis/MATreeMapDataViewController.h>
#import <MobileAnalysis/PPLDimension.h>
#import <MobileAnalysis/PPLFileManager.h>
#import <MobileAnalysis/PPLibBubbleTreeDataSource.h>
#import <MobileAnalysis/SettingsColorPicker.h>
#import <MobileAnalysis/SettingsPaletteSelector.h>
#import <MobileAnalysis/TreeMapSettings.h>
#import <MobileAnalysis/TrendLine.h>
#include "MABaseReportViewController.h"
#include "MAElementDataSourceRoleSelectorViewController.h"
#include "MAExpressAnalysisReportViewController.h"
#include "MAExpressAnalysisReportViewControllerDelegate.h"
#include "MAExpressAnalysisReportViewControllerDelegateImpl.h"
#include "MAExpressAnalysisReportViewControllerFactory.h"
#include "MapDataViewDatasource.h"
#include "NData.h"
#include "NNotificationCenterExt.h"
#include "PPLAccessRightsManager.h"
#include "PPLCalendarDimension.h"
#include "PPLCubeDataSource.h"
#include "PPLMetabase.h"
#include "PPLMetabaseRepositoryWarehousePool.h"
#include "PPLOlapReportPlistKeys.h"
#include "PPLPivotTableConditionFilter.h"
#include "PPLPivotTableConditionFilterFactory.h"
#include "PPLPivotTableGlobalConditionFilter.h"
#include "PPLProceduralReportFactory.h"
#include "PPLRubricatorDataSource.h"
#include "PPLRubricatorTableField.h"
#include <MobileAnalysis/ChartSettingsViewController.h>
#include <MobileAnalysis/MAConditionalFormatting.h>
@interface ViewController()
    @property (retain) UIAlertView* waiterView;
    @property (assign) int signingAttempsCount;
@end
@implementation ViewController
const int static delay = 3;
const int maxSigningAttempsCount = 3; // Количество попыток подключения к репозиторию
NSString *host = @"nrspo-121.prognozcloud.ru/r7.2/mobile";
NSString *login = @"sa";
NSString *password = @"sa";
-(id)init {
    self = [super init];
    if (self) {
        [self setSigningAttempsCount: 0];
        // Устанавливаем обработчик события успешного скачивания отчёта
        NNotificationCenterExt::addObserver(self, @selector(repositoryDownloadingFinished:), didDownloadRepositoryDescriptorNotificationName, NULL);
        // Устанавливаем обработчик события неуспешного скачивания отчёта
        NNotificationCenterExt::addObserver(self, @selector(repositoryDownloadingFailed:), didFailDownloadingRepositoryDescriptorNotificationName, NULL);
        // Устанавливаем обработчик события завершения аутентификации
        NNotificationCenterExt::addObserver(self, @selector(authenticationCompleted:), didAuthenticationCompletedDescriptorNotificationName, NULL);
        [self showWaiterWithText: NSLocalizedString(@"Signing in...", nil)];
        // Подключаемся к репозиторию
        [self connect];
    }
    return self;
}
-(void) connect {
    // Создаём репозиторий, содержащую информацию об отчетах
    m_metabase = PPLMetabase::sharedMetabase(NString::stringWithNSString([NSString stringWithFormat:@"http://%@",host]));
    m_metabase->setHost(NString::stringWithNSString(host));
    if (m_metabase->getHost() == nil) {
        m_metabase->setHost(NString::stringWithNSString(host));
    }
    if (m_metabase->isHttpsEnabled()) {
        m_metabase->setHttpsEnabled(false);
    }
    [self updateRepository];
    // Аутентифицируем пользователя
    [self authenticateUser];
}
// Аутентифицирует пользователя
-(void)authenticateUser {
    /* Устанавливаем логин и пароль для проверки,
    может ли указанный пользователь получить доступ к отчётам */
    PPLAccessRightsManager::accessRightsManager()->setAuthenticatedUser(m_metabase->getLogin(), m_metabase->getPassword());
}
// Обновляет состояние репозитория на основе данных на удалённом сервере
-(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(@"Ошибка авторизации (попытка %d)", _signingAttempsCount);
        if (_signingAttempsCount < maxSigningAttempsCount) {
            [self connect];
            } else {
            [self hideWaiter];
        }
    }
}
- (void)repositoryDownloadingFinished:(NNotification *)notification {
    NSLog(@"Данные репозитория успешно получены");
    [self hideWaiter];
    [self initObjectDescriptor];
}
- (void)repositoryDownloadingFailed:(NNotification *)notification {
    NSLog(@"Ошибка загрузки данных репозитория");
}
// Инициализирует объект репозитория
-(void)initObjectDescriptor {
    N_FOREACH(SPPLMetabaseRepositoryDescriptor, repositoryDescriptor, [self getRepositories]) {
        // Устанавливаем репозиторий в качестве текущего
        [self setCurrentRepository: repositoryDescriptor];
        // Получаем экспресс-отчет
        SPPLMetabaseRepositoryObjectDescriptor olapObjectDescriptor =
        [self getObjectDescriptorWithType: PPLMetabaseRepositoryObjectDescriptor::kExpressAnalysisReport];
        // Удаляем данный отчёт
        if ([self removeRepositoryObject: olapObjectDescriptor]) {
            return;
        };
        // Загружаем описание объекта репозитория
        bool isDownloading = [self downloadRepositoryObject: olapObjectDescriptor];
        if (isDownloading) {
            return;
        }
    }
}
// Устанавливает текущий репозиторий
-(void)setCurrentRepository: (SPPLMetabaseRepositoryDescriptor) repositoryDescriptor {
    m_metabase = PPLMetabase::sharedMetabase(repositoryDescriptor);
}
// Возвращает массив репозиториев
-(SNArray) getRepositories {
    SPPLMetabaseRepositoryWarehouse defaultWarehouse = PPLMetabaseRepositoryWarehousePool::sharedWarehousePool()->defaultWarehouse();
    return defaultWarehouse->repositoriesList();
}
// Возвращает описание объекта репозитория указанного типа
-(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;
}
// Удаляет указанный объект репозитория
-(bool)removeRepositoryObject: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor {
    if (objectDescriptor && objectDescriptor->isLocal()) {
        [self removeReport: objectDescriptor];
        NSLog(@"Объект репозитория удалён");
        return true;
        } else {
        return false;
    }
}
// Загружает указанный объект репозитория
-(bool)downloadRepositoryObject: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor {
    if (objectDescriptor && objectDescriptor->isRemote()) {
        [self downloadReport: objectDescriptor];
        return true;
        } else {
        return false;
    }
}
-(void) downloadReport: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor {
    [self addObjectDownloadObservers];
    m_olapReportDescriptor = objectDescriptor;
    m_metabase->downloadReport(objectDescriptor);
    [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_olapReportDescriptor->isLocal()) {
        NSLog(@"Отчёт успешно загружен");
        [self hideWaiter];
        [self showWaiterWithText: NSLocalizedString(@"Opening...", nil)];
        [self removeObjectDownloadObservers];
        // Открываем отчёт
        [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);
}
// Отображает индикатор занятости
- (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];
}
// Удаляем индикатор занятости
- (void)hideWaiter {
    [[self waiterView] dismissWithClickedButtonIndex:0 animated:NO];
    [self setWaiterView: nil];
}
// Удаляет указанный объект репозитория
-(void)removeReport: (SPPLMetabaseRepositoryObjectDescriptor) objectDescriptor {
    m_metabase->removeObject(objectDescriptor);
    // Обновляем состояние репозитория
    [self updateRepository];
}
// Отображает представление контроллера в полноэкранном режиме
-(void) showViewControllerInFullScreen: (UIViewController *) viewController {
    [self showViewInFullScreen: [viewController view]];
}
// Отображает указанное представление в полноэкранном режиме
-(void) showViewInFullScreen: (UIView *) view {
    // Удаляем все дочерние представления окна
    NSArray *subviews = [self.view subviews];
    for (UIView *subView in subviews) {
        [subView removeFromSuperview];
    }
    // Отображаем представление контроллера
    [[self view] addSubview: view];
}
// Отображает представление контроллера в полноэкранном режиме
-(void) showViewControllerInNavigationController: (UIViewController *) viewController {
    UINavigationController *navigationCtrl = [[UINavigationController alloc] initWithRootViewController: viewController];
    // Отображаем представление контроллера
    [self showViewControllerInFullScreen: navigationCtrl];
}
// Отображает представление в полноэкранном режиме
-(void) showViewInNavigationController: (UIView *) view {
    UINavigationController *navigationCtrl = [UINavigationController new];
    [[navigationCtrl view] addSubview: view];
    // Отображаем представление контроллера
    [self showViewControllerInFullScreen: navigationCtrl];
}
// Отображает представление контроллера в всплывающем окне
-(void) showViewControllerInPopover: (UIViewController *) viewController {
    UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController: viewController];
    [popover presentPopoverFromRect:[[viewController view] frame] inView:[self view] permittedArrowDirections:NULL animated:NO];
}
// Открывает отчёт с аналитическими панелями
-(void) openReport {
    // Создаём объект экспресс-отчёта
    m_olapReport = PPLOlapReport::olapReport(m_olapReportDescriptor);
    m_controller = [MAExpressAnalysisReportViewControllerFactory createReport:m_olapReport];
    // Отображаем отчёт с аналитическими панелями
    [self showReport: m_controller];
    [self hideWaiter];
    // Выполняем пользовательский пример
    [self performSelector:@selector(executeExample) withObject:NULL afterDelay:delay];
}
// Отображает экспресс-отчёт
- (void)showReport:(UIViewController *)controller {
    [self showViewControllerInNavigationController: controller];
}
// Возвращает все измерения данных
- (SNArray)allDimensions {
    SPPLPivot pivot = PPLPivot::pivot(m_olapReport);
    SNMutableArray allDimensions = NMutableArray::mutableArrayWithArray(pivot->topHeader()->dimensions());
    allDimensions->addObjectsFromArray(pivot->leftHeader()->dimensions());
    allDimensions->addObjectsFromArray(pivot->fixedHeader()->dimensions());
    return allDimensions;
}
- (void)viewDidLoad {
    [super viewDidLoad];
}
-(void)executeExample {
}
@end

См. также:

Отображение экспресс-отчёта