LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/core/data - dptabsrc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 994 1351 73.6 %
Date: 2013-07-09 Functions: 135 206 65.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "dptabsrc.hxx"
      21             : 
      22             : #include <algorithm>
      23             : #include <vector>
      24             : #include <set>
      25             : #include <boost/unordered_set.hpp>
      26             : #include <boost/unordered_map.hpp>
      27             : 
      28             : #include <rtl/math.hxx>
      29             : #include <svl/itemprop.hxx>
      30             : #include <svl/intitem.hxx>
      31             : #include <vcl/svapp.hxx>
      32             : 
      33             : #include "scitems.hxx"
      34             : #include "document.hxx"
      35             : #include "docpool.hxx"
      36             : #include "patattr.hxx"
      37             : #include "formulacell.hxx"
      38             : 
      39             : #include "dptabres.hxx"
      40             : #include "dptabdat.hxx"
      41             : #include "global.hxx"
      42             : #include "datauno.hxx"      // ScDataUnoConversion
      43             : #include "miscuno.hxx"
      44             : #include "unonames.hxx"
      45             : #include "dpitemdata.hxx"
      46             : #include "dputil.hxx"
      47             : #include "dpresfilter.hxx"
      48             : #include "calcmacros.hxx"
      49             : 
      50             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      51             : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
      52             : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      53             : #include <com/sun/star/sheet/DataPilotFieldReferenceType.hpp>
      54             : #include <com/sun/star/sheet/DataPilotFieldSortMode.hpp>
      55             : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
      56             : #include <com/sun/star/sheet/DataPilotFieldAutoShowInfo.hpp>
      57             : #include <com/sun/star/table/CellAddress.hpp>
      58             : 
      59             : #include "comphelper/string.hxx"
      60             : #include <unotools/collatorwrapper.hxx>
      61             : #include <unotools/calendarwrapper.hxx>
      62             : #include <com/sun/star/i18n/CalendarDisplayIndex.hpp>
      63             : 
      64             : using namespace com::sun::star;
      65             : using ::std::vector;
      66             : using ::std::set;
      67             : using ::com::sun::star::uno::Reference;
      68             : using ::com::sun::star::uno::Sequence;
      69             : using ::com::sun::star::uno::Any;
      70             : using ::com::sun::star::sheet::DataPilotFieldAutoShowInfo;
      71             : 
      72             : // -----------------------------------------------------------------------
      73             : 
      74             : #define SC_MINCOUNT_LIMIT   1000000
      75             : 
      76             : // -----------------------------------------------------------------------
      77             : 
      78           0 : SC_SIMPLE_SERVICE_INFO( ScDPSource,      "ScDPSource",      "com.sun.star.sheet.DataPilotSource" )
      79           0 : SC_SIMPLE_SERVICE_INFO( ScDPDimensions,  "ScDPDimensions",  "com.sun.star.sheet.DataPilotSourceDimensions" )
      80           0 : SC_SIMPLE_SERVICE_INFO( ScDPDimension,   "ScDPDimension",   "com.sun.star.sheet.DataPilotSourceDimension" )
      81           0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchies, "ScDPHierarchies", "com.sun.star.sheet.DataPilotSourceHierarcies" )
      82           0 : SC_SIMPLE_SERVICE_INFO( ScDPHierarchy,   "ScDPHierarchy",   "com.sun.star.sheet.DataPilotSourceHierarcy" )
      83           0 : SC_SIMPLE_SERVICE_INFO( ScDPLevels,      "ScDPLevels",      "com.sun.star.sheet.DataPilotSourceLevels" )
      84           0 : SC_SIMPLE_SERVICE_INFO( ScDPLevel,       "ScDPLevel",       "com.sun.star.sheet.DataPilotSourceLevel" )
      85           0 : SC_SIMPLE_SERVICE_INFO( ScDPMembers,     "ScDPMembers",     "com.sun.star.sheet.DataPilotSourceMembers" )
      86           0 : SC_SIMPLE_SERVICE_INFO( ScDPMember,      "ScDPMember",      "com.sun.star.sheet.DataPilotSourceMember" )
      87             : 
      88             : // -----------------------------------------------------------------------
      89             : 
      90             : // property maps for PropertySetInfo
      91             : //  DataDescription / NumberFormat are internal
      92             : 
      93             : // -----------------------------------------------------------------------
      94             : 
      95             : //! move to a header?
      96         955 : static sal_Bool lcl_GetBoolFromAny( const uno::Any& aAny )
      97             : {
      98         955 :     if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN )
      99         955 :         return *(sal_Bool*)aAny.getValue();
     100           0 :     return false;
     101             : }
     102             : 
     103        3541 : static void lcl_SetBoolInAny( uno::Any& rAny, sal_Bool bValue )
     104             : {
     105        3541 :     rAny.setValue( &bValue, getBooleanCppuType() );
     106        3541 : }
     107             : 
     108             : // -----------------------------------------------------------------------
     109             : 
     110         102 : ScDPSource::ScDPSource( ScDPTableData* pD ) :
     111             :     pData( pD ),
     112             :     pDimensions( NULL ),
     113             :     bColumnGrand( true ),       // default is true
     114             :     bRowGrand( true ),
     115             :     bIgnoreEmptyRows( false ),
     116             :     bRepeatIfEmpty( false ),
     117             :     nDupCount( 0 ),
     118             :     pResData( NULL ),
     119             :     pColResRoot( NULL ),
     120             :     pRowResRoot( NULL ),
     121             :     pColResults( NULL ),
     122             :     pRowResults( NULL ),
     123             :     bResultOverflow( false ),
     124             :     bPageFiltered( false ),
     125         102 :     mpGrandTotalName(NULL)
     126             : {
     127         102 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     128         102 : }
     129             : 
     130         306 : ScDPSource::~ScDPSource()
     131             : {
     132         102 :     if (pDimensions)
     133         102 :         pDimensions->release();     // ref-counted
     134             : 
     135             :     //! free lists
     136             : 
     137         102 :     delete[] pColResults;
     138         102 :     delete[] pRowResults;
     139             : 
     140         102 :     delete pColResRoot;
     141         102 :     delete pRowResRoot;
     142         102 :     delete pResData;
     143         204 : }
     144             : 
     145          99 : const OUString* ScDPSource::GetGrandTotalName() const
     146             : {
     147          99 :     return mpGrandTotalName.get();
     148             : }
     149             : 
     150        3090 : sal_uInt16 ScDPSource::GetOrientation(long nColumn)
     151             : {
     152        3090 :     if (std::find(maColDims.begin(), maColDims.end(), nColumn) != maColDims.end())
     153         785 :         return sheet::DataPilotFieldOrientation_COLUMN;
     154             : 
     155        2305 :     if (std::find(maRowDims.begin(), maRowDims.end(), nColumn) != maRowDims.end())
     156        1029 :         return sheet::DataPilotFieldOrientation_ROW;
     157             : 
     158        1276 :     if (std::find(maDataDims.begin(), maDataDims.end(), nColumn) != maDataDims.end())
     159         517 :         return sheet::DataPilotFieldOrientation_DATA;
     160             : 
     161         759 :     if (std::find(maPageDims.begin(), maPageDims.end(), nColumn) != maPageDims.end())
     162          52 :         return sheet::DataPilotFieldOrientation_PAGE;
     163             : 
     164         707 :     return sheet::DataPilotFieldOrientation_HIDDEN;
     165             : }
     166             : 
     167           7 : long ScDPSource::GetDataDimensionCount()
     168             : {
     169           7 :     return maDataDims.size();
     170             : }
     171             : 
     172         105 : ScDPDimension* ScDPSource::GetDataDimension(long nIndex)
     173             : {
     174         105 :     if (nIndex < 0 || static_cast<size_t>(nIndex) >= maDataDims.size())
     175          10 :         return NULL;
     176             : 
     177          95 :     long nDimIndex = maDataDims[nIndex];
     178          95 :     return GetDimensionsObject()->getByIndex(nDimIndex);
     179             : }
     180             : 
     181          17 : OUString ScDPSource::GetDataDimName(long nIndex)
     182             : {
     183          17 :     OUString aRet;
     184          17 :     ScDPDimension* pDim = GetDataDimension(nIndex);
     185          17 :     if (pDim)
     186          17 :         aRet = pDim->getName();
     187          17 :     return aRet;
     188             : }
     189             : 
     190         400 : long ScDPSource::GetPosition(long nColumn)
     191             : {
     192         400 :     std::vector<long>::const_iterator it, itBeg = maColDims.begin(), itEnd = maColDims.end();
     193         400 :     it = std::find(itBeg, itEnd, nColumn);
     194         400 :     if (it != itEnd)
     195          45 :         return std::distance(itBeg, it);
     196             : 
     197         355 :     itBeg = maRowDims.begin();
     198         355 :     itEnd = maRowDims.end();
     199         355 :     it = std::find(itBeg, itEnd, nColumn);
     200         355 :     if (it != itEnd)
     201         112 :         return std::distance(itBeg, it);
     202             : 
     203         243 :     itBeg = maDataDims.begin();
     204         243 :     itEnd = maDataDims.end();
     205         243 :     it = std::find(itBeg, itEnd, nColumn);
     206         243 :     if (it != itEnd)
     207          74 :         return std::distance(itBeg, it);
     208             : 
     209         169 :     itBeg = maPageDims.begin();
     210         169 :     itEnd = maPageDims.end();
     211         169 :     it = std::find(itBeg, itEnd, nColumn);
     212         169 :     if (it != itEnd)
     213          21 :         return std::distance(itBeg, it);
     214             : 
     215         148 :     return 0;
     216             : }
     217             : 
     218             : namespace {
     219             : 
     220        8846 : bool testSubTotal( bool& rAllowed, long nColumn, const std::vector<long>& rDims, ScDPSource* pSource )
     221             : {
     222        8846 :     rAllowed = true;
     223        8846 :     std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
     224       11211 :     for (; it != itEnd; ++it)
     225             :     {
     226        9184 :         if (*it != nColumn)
     227        2365 :             continue;
     228             : 
     229        6819 :         if ( pSource->IsDataLayoutDimension(nColumn) )
     230             :         {
     231             :             //  no subtotals for data layout dim, no matter where
     232         126 :             rAllowed = false;
     233         126 :             return true;
     234             :         }
     235             : 
     236             :         //  no subtotals if no other dim but data layout follows
     237        6693 :         ++it;
     238        6693 :         if (it != itEnd && pSource->IsDataLayoutDimension(*it))
     239         914 :             ++it;
     240        6693 :         if (it == itEnd)
     241        5420 :             rAllowed = false;
     242             : 
     243        6693 :         return true;    // found
     244             :     }
     245             : 
     246        2027 :     return false;
     247             : }
     248             : 
     249        3120 : void removeDim( long nRemove, std::vector<long>& rDims )
     250             : {
     251        3120 :     std::vector<long>::iterator it = std::find(rDims.begin(), rDims.end(), nRemove);
     252        3120 :     if (it != rDims.end())
     253           0 :         rDims.erase(it);
     254        3120 : }
     255             : 
     256             : }
     257             : 
     258        6819 : sal_Bool ScDPSource::SubTotalAllowed(long nColumn)
     259             : {
     260             :     //! cache this at ScDPResultData
     261        6819 :     bool bAllowed = true;
     262        6819 :     if ( testSubTotal(bAllowed, nColumn, maColDims, this) )
     263        4792 :         return bAllowed;
     264        2027 :     if ( testSubTotal(bAllowed, nColumn, maRowDims, this) )
     265        2027 :         return bAllowed;
     266           0 :     return bAllowed;
     267             : }
     268             : 
     269         780 : void ScDPSource::SetOrientation(long nColumn, sal_uInt16 nNew)
     270             : {
     271             :     //! change to no-op if new orientation is equal to old?
     272             : 
     273             :     // remove from old list
     274         780 :     removeDim(nColumn, maColDims);
     275         780 :     removeDim(nColumn, maRowDims);
     276         780 :     removeDim(nColumn, maDataDims);
     277         780 :     removeDim(nColumn, maPageDims);
     278             : 
     279             :     // add to new list
     280         780 :     switch (nNew)
     281             :     {
     282             :         case sheet::DataPilotFieldOrientation_COLUMN:
     283          46 :             maColDims.push_back(nColumn);
     284          46 :             break;
     285             :         case sheet::DataPilotFieldOrientation_ROW:
     286         114 :             maRowDims.push_back(nColumn);
     287         114 :             break;
     288             :         case sheet::DataPilotFieldOrientation_DATA:
     289          75 :             maDataDims.push_back(nColumn);
     290          75 :             break;
     291             :         case sheet::DataPilotFieldOrientation_PAGE:
     292          22 :             maPageDims.push_back(nColumn);
     293          22 :             break;
     294             :             // DataPilot Migration - Cache&&Performance
     295             :         case sheet::DataPilotFieldOrientation_HIDDEN:
     296         523 :             break;
     297             :         default:
     298             :             OSL_FAIL( "ScDPSource::SetOrientation: unexpected orientation" );
     299           0 :             break;
     300             :     }
     301         780 : }
     302             : 
     303       10485 : sal_Bool ScDPSource::IsDataLayoutDimension(long nDim)
     304             : {
     305       10485 :     return nDim == pData->GetColumnCount();
     306             : }
     307             : 
     308         156 : sal_uInt16 ScDPSource::GetDataLayoutOrientation()
     309             : {
     310         156 :     return GetOrientation(pData->GetColumnCount());
     311             : }
     312             : 
     313        1717 : sal_Bool ScDPSource::IsDateDimension(long nDim)
     314             : {
     315        1717 :     return pData->IsDateDimension(nDim);
     316             : }
     317             : 
     318        3982 : ScDPDimensions* ScDPSource::GetDimensionsObject()
     319             : {
     320        3982 :     if (!pDimensions)
     321             :     {
     322         110 :         pDimensions = new ScDPDimensions(this);
     323         110 :         pDimensions->acquire();                     // ref-counted
     324             :     }
     325        3982 :     return pDimensions;
     326             : }
     327             : 
     328        1094 : uno::Reference<container::XNameAccess> SAL_CALL ScDPSource::getDimensions() throw(uno::RuntimeException)
     329             : {
     330        1094 :     return GetDimensionsObject();
     331             : }
     332             : 
     333          10 : void ScDPSource::SetDupCount( long nNew )
     334             : {
     335          10 :     nDupCount = nNew;
     336          10 : }
     337             : 
     338           2 : ScDPDimension* ScDPSource::AddDuplicated(long /* nSource */, const OUString& rNewName)
     339             : {
     340             :     OSL_ENSURE( pDimensions, "AddDuplicated without dimensions?" );
     341             : 
     342             :     //  re-use
     343             : 
     344           2 :     long nOldDimCount = pDimensions->getCount();
     345           8 :     for (long i=0; i<nOldDimCount; i++)
     346             :     {
     347           6 :         ScDPDimension* pDim = pDimensions->getByIndex(i);
     348           6 :         if (pDim && pDim->getName().equals(rNewName))
     349             :         {
     350             :             //! test if pDim is a duplicate of source
     351           0 :             return pDim;
     352             :         }
     353             :     }
     354             : 
     355           2 :     SetDupCount( nDupCount + 1 );
     356           2 :     pDimensions->CountChanged();        // uses nDupCount
     357             : 
     358           2 :     return pDimensions->getByIndex( pDimensions->getCount() - 1 );
     359             : }
     360             : 
     361       14377 : long ScDPSource::GetSourceDim(long nDim)
     362             : {
     363             :     //  original source dimension or data layout dimension?
     364       14377 :     if ( nDim <= pData->GetColumnCount() )
     365       14361 :         return nDim;
     366             : 
     367          16 :     if ( nDim < pDimensions->getCount() )
     368             :     {
     369          16 :         ScDPDimension* pDimObj = pDimensions->getByIndex( nDim );
     370          16 :         if ( pDimObj )
     371             :         {
     372          16 :             long nSource = pDimObj->GetSourceDim();
     373          16 :             if ( nSource >= 0 )
     374          16 :                 return nSource;
     375             :         }
     376             :     }
     377             : 
     378             :     OSL_FAIL("GetSourceDim: wrong dim");
     379           0 :     return nDim;
     380             : }
     381             : 
     382          78 : uno::Sequence< uno::Sequence<sheet::DataResult> > SAL_CALL ScDPSource::getResults()
     383             :                                                             throw(uno::RuntimeException)
     384             : {
     385          78 :     CreateRes_Impl();       // create pColResRoot and pRowResRoot
     386             : 
     387          78 :     if ( bResultOverflow )      // set in CreateRes_Impl
     388             :     {
     389             :         //  no results available
     390           0 :         throw uno::RuntimeException();
     391             :     }
     392             : 
     393          78 :     long nColCount = pColResRoot->GetSize(pResData->GetColStartMeasure());
     394          78 :     long nRowCount = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
     395             : 
     396             :     //  allocate full sequence
     397             :     //! leave out empty rows???
     398             : 
     399          78 :     uno::Sequence< uno::Sequence<sheet::DataResult> > aSeq( nRowCount );
     400          78 :     uno::Sequence<sheet::DataResult>* pRowAry = aSeq.getArray();
     401         438 :     for (long nRow = 0; nRow < nRowCount; nRow++)
     402             :     {
     403         360 :         uno::Sequence<sheet::DataResult> aColSeq( nColCount );
     404             :         //  use default values of DataResult
     405         360 :         pRowAry[nRow] = aColSeq;
     406         360 :     }
     407             : 
     408         156 :     ScDPResultFilterContext aFilterCxt;
     409             :     pRowResRoot->FillDataResults(
     410          78 :         pColResRoot, aFilterCxt, aSeq, pResData->GetRowStartMeasure());
     411             : 
     412          78 :     maResFilterSet.swap(aFilterCxt.maFilterSet); // Keep this data for GETPIVOTDATA.
     413             : 
     414         156 :     return aSeq;
     415             : }
     416             : 
     417           0 : uno::Sequence<double> ScDPSource::getFilteredResults(
     418             :             const uno::Sequence<sheet::DataPilotFieldFilter>& aFilters )
     419             :                 throw (uno::RuntimeException)
     420             : {
     421           0 :     if (maResFilterSet.empty())
     422           0 :         getResults(); // Build result tree first.
     423             : 
     424             :     // Get result values from the tree.
     425           0 :     const ScDPResultTree::ValuesType* pVals = maResFilterSet.getResults(aFilters);
     426           0 :     if (!pVals)
     427           0 :         return uno::Sequence<double>();
     428             : 
     429           0 :     size_t n = pVals->size();
     430           0 :     uno::Sequence<double> aRet(n);
     431           0 :     for (size_t i = 0; i < n; ++i)
     432           0 :         aRet[i] = (*pVals)[i];
     433             : 
     434           0 :     return aRet;
     435             : }
     436             : 
     437           8 : void SAL_CALL ScDPSource::refresh() throw(uno::RuntimeException)
     438             : {
     439           8 :     disposeData();
     440           8 : }
     441             : 
     442           0 : void SAL_CALL ScDPSource::addRefreshListener( const uno::Reference<util::XRefreshListener >& )
     443             :                                                 throw(uno::RuntimeException)
     444             : {
     445             :     OSL_FAIL("not implemented");    //! exception?
     446           0 : }
     447             : 
     448           0 : void SAL_CALL ScDPSource::removeRefreshListener( const uno::Reference<util::XRefreshListener >& )
     449             :                                                 throw(uno::RuntimeException)
     450             : {
     451             :     OSL_FAIL("not implemented");    //! exception?
     452           0 : }
     453             : 
     454         133 : Sequence< Sequence<Any> > SAL_CALL ScDPSource::getDrillDownData(const Sequence<sheet::DataPilotFieldFilter>& aFilters)
     455             :     throw (uno::RuntimeException)
     456             : {
     457         133 :     long nColumnCount = GetData()->GetColumnCount();
     458             : 
     459         133 :     vector<ScDPFilteredCache::Criterion> aFilterCriteria;
     460         133 :     sal_Int32 nFilterCount = aFilters.getLength();
     461         593 :     for (sal_Int32 i = 0; i < nFilterCount; ++i)
     462             :     {
     463         460 :         const sheet::DataPilotFieldFilter& rFilter = aFilters[i];
     464         460 :         const OUString& aFieldName = rFilter.FieldName;
     465        2760 :         for (long nCol = 0; nCol < nColumnCount; ++nCol)
     466             :         {
     467        2300 :             if (aFieldName.equals(pData->getDimensionName(nCol)))
     468             :             {
     469         460 :                 ScDPDimension* pDim = GetDimensionsObject()->getByIndex( nCol );
     470         460 :                 ScDPMembers* pMembers = pDim->GetHierarchiesObject()->getByIndex(0)->
     471         460 :                                         GetLevelsObject()->getByIndex(0)->GetMembersObject();
     472         460 :                 sal_Int32 nIndex = pMembers->GetIndexFromName( rFilter.MatchValue );
     473         460 :                 if ( nIndex >= 0 )
     474             :                 {
     475         460 :                     ScDPItemData aItem;
     476         460 :                     pMembers->getByIndex(nIndex)->FillItemData( aItem );
     477         460 :                     aFilterCriteria.push_back( ScDPFilteredCache::Criterion() );
     478         460 :                     aFilterCriteria.back().mnFieldIndex = nCol;
     479         460 :                     aFilterCriteria.back().mpFilter.reset(
     480         920 :                         new ScDPFilteredCache::SingleFilter(aItem));
     481             :                 }
     482             :             }
     483             :         }
     484             :     }
     485             : 
     486             :     // Take into account the visibilities of field members.
     487         266 :     ScDPResultVisibilityData aResVisData(this);
     488         133 :     pRowResRoot->FillVisibilityData(aResVisData);
     489         133 :     pColResRoot->FillVisibilityData(aResVisData);
     490         133 :     aResVisData.fillFieldFilters(aFilterCriteria);
     491             : 
     492         133 :     Sequence< Sequence<Any> > aTabData;
     493         266 :     boost::unordered_set<sal_Int32> aCatDims;
     494         133 :     GetCategoryDimensionIndices(aCatDims);
     495         133 :     pData->GetDrillDownData(aFilterCriteria, aCatDims, aTabData);
     496         266 :     return aTabData;
     497             : }
     498             : 
     499          78 : OUString ScDPSource::getDataDescription()
     500             : {
     501          78 :     CreateRes_Impl();       // create pResData
     502             : 
     503          78 :     OUString aRet;
     504          78 :     if ( pResData->GetMeasureCount() == 1 )
     505             :     {
     506          72 :         bool bTotalResult = false;
     507          72 :         aRet = pResData->GetMeasureString(0, true, SUBTOTAL_FUNC_NONE, bTotalResult);
     508             :     }
     509             : 
     510             :     //  empty for more than one measure
     511             : 
     512          78 :     return aRet;
     513             : }
     514             : 
     515         110 : void ScDPSource::setIgnoreEmptyRows(bool bSet)
     516             : {
     517         110 :     bIgnoreEmptyRows = bSet;
     518         110 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     519         110 : }
     520             : 
     521         110 : void ScDPSource::setRepeatIfEmpty(bool bSet)
     522             : {
     523         110 :     bRepeatIfEmpty = bSet;
     524         110 :     pData->SetEmptyFlags( bIgnoreEmptyRows, bRepeatIfEmpty );
     525         110 : }
     526             : 
     527           8 : void ScDPSource::disposeData()
     528             : {
     529           8 :     maResFilterSet.clear();
     530             : 
     531           8 :     if ( pResData )
     532             :     {
     533             :         //  reset all data...
     534             : 
     535           8 :         DELETEZ(pColResRoot);
     536           8 :         DELETEZ(pRowResRoot);
     537           8 :         DELETEZ(pResData);
     538           8 :         delete[] pColResults;
     539           8 :         delete[] pRowResults;
     540           8 :         pColResults = NULL;
     541           8 :         pRowResults = NULL;
     542           8 :         aColLevelList.clear();
     543           8 :         aRowLevelList.clear();
     544             :     }
     545             : 
     546           8 :     if ( pDimensions )
     547             :     {
     548           8 :         pDimensions->release(); // ref-counted
     549           8 :         pDimensions = NULL;     //  settings have to be applied (from SaveData) again!
     550             :     }
     551           8 :     SetDupCount( 0 );
     552             : 
     553           8 :     maColDims.clear();
     554           8 :     maRowDims.clear();
     555           8 :     maDataDims.clear();
     556           8 :     maPageDims.clear();
     557             : 
     558           8 :     pData->DisposeData();   // cached entries etc.
     559           8 :     bPageFiltered = false;
     560           8 :     bResultOverflow = false;
     561           8 : }
     562             : 
     563         156 : static long lcl_CountMinMembers(const vector<ScDPDimension*>& ppDim, const vector<ScDPLevel*>& ppLevel, long nLevels )
     564             : {
     565             :     //  Calculate the product of the member count for those consecutive levels that
     566             :     //  have the "show all" flag, one following level, and the data layout dimension.
     567             : 
     568         156 :     long nTotal = 1;
     569         156 :     long nDataCount = 1;
     570         156 :     sal_Bool bWasShowAll = sal_True;
     571         156 :     long nPos = nLevels;
     572         434 :     while ( nPos > 0 )
     573             :     {
     574         122 :         --nPos;
     575             : 
     576         122 :         if ( nPos+1 < nLevels && ppDim[nPos] == ppDim[nPos+1] )
     577             :         {
     578             :             OSL_FAIL("lcl_CountMinMembers: multiple levels from one dimension not implemented");
     579           0 :             return 0;
     580             :         }
     581             : 
     582         122 :         sal_Bool bDo = false;
     583         122 :         if ( ppDim[nPos]->getIsDataLayoutDimension() )
     584             :         {
     585             :             //  data layout dim doesn't interfere with "show all" flags
     586           6 :             nDataCount = ppLevel[nPos]->GetMembersObject()->getCount();
     587           6 :             if ( nDataCount == 0 )
     588           0 :                 nDataCount = 1;
     589             :         }
     590         116 :         else if ( bWasShowAll )     // "show all" set for all following levels?
     591             :         {
     592         100 :             bDo = sal_True;
     593         100 :             if ( !ppLevel[nPos]->getShowEmpty() )
     594             :             {
     595             :                 //  this level is counted, following ones are not
     596         100 :                 bWasShowAll = false;
     597             :             }
     598             :         }
     599         122 :         if ( bDo )
     600             :         {
     601         100 :             long nThisCount = ppLevel[nPos]->GetMembersObject()->getMinMembers();
     602         100 :             if ( nThisCount == 0 )
     603             :             {
     604           0 :                 nTotal = 1;         //  empty level -> start counting from here
     605             :                                     //! start with visible elements in this level?
     606             :             }
     607             :             else
     608             :             {
     609         100 :                 if ( nTotal >= LONG_MAX / nThisCount )
     610           0 :                     return LONG_MAX;                        //  overflow
     611         100 :                 nTotal *= nThisCount;
     612             :             }
     613             :         }
     614             :     }
     615             : 
     616             :     //  always include data layout dim, even after restarting
     617         156 :     if ( nTotal >= LONG_MAX / nDataCount )
     618           0 :         return LONG_MAX;                        //  overflow
     619         156 :     nTotal *= nDataCount;
     620             : 
     621         156 :     return nTotal;
     622             : }
     623             : 
     624           4 : static long lcl_GetIndexFromName( const OUString rName, const uno::Sequence<OUString>& rElements )
     625             : {
     626           4 :     long nCount = rElements.getLength();
     627           4 :     const OUString* pArray = rElements.getConstArray();
     628           4 :     for (long nPos=0; nPos<nCount; nPos++)
     629           4 :         if (pArray[nPos] == rName)
     630           4 :             return nPos;
     631             : 
     632           0 :     return -1;  // not found
     633             : }
     634             : 
     635         156 : void ScDPSource::FillCalcInfo(bool bIsRow, ScDPTableData::CalcInfo& rInfo, bool &rHasAutoShow)
     636             : {
     637         156 :     const std::vector<long>& rDims = bIsRow ? maRowDims : maColDims;
     638         156 :     std::vector<long>::const_iterator it = rDims.begin(), itEnd = rDims.end();
     639         313 :     for (; it != itEnd; ++it)
     640             :     {
     641         157 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     642         157 :         long nHierarchy = pDim->getUsedHierarchy();
     643         157 :         if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
     644           0 :             nHierarchy = 0;
     645         157 :         ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
     646         157 :         long nCount = pLevels->getCount();
     647             : 
     648             :         //! Test
     649         157 :         if (pDim->getIsDataLayoutDimension() && maDataDims.size() < 2)
     650          35 :             nCount = 0;
     651             :         //! Test
     652             : 
     653         279 :         for (long j = 0; j < nCount; ++j)
     654             :         {
     655         122 :             ScDPLevel* pLevel = pLevels->getByIndex(j);
     656         122 :             pLevel->EvaluateSortOrder();
     657             : 
     658             :             // no layout flags for column fields, only for row fields
     659         122 :             pLevel->SetEnableLayout( bIsRow );
     660             : 
     661         122 :             if ( pLevel->GetAutoShow().IsEnabled )
     662           1 :                 rHasAutoShow = true;
     663             : 
     664         122 :             if (bIsRow)
     665             :             {
     666          77 :                 rInfo.aRowLevelDims.push_back(*it);
     667          77 :                 rInfo.aRowDims.push_back(pDim);
     668          77 :                 rInfo.aRowLevels.push_back(pLevel);
     669             :             }
     670             :             else
     671             :             {
     672          45 :                 rInfo.aColLevelDims.push_back(*it);
     673          45 :                 rInfo.aColDims.push_back(pDim);
     674          45 :                 rInfo.aColLevels.push_back(pLevel);
     675             :             }
     676             : 
     677         122 :             pLevel->GetMembersObject();                 // initialize for groups
     678             :         }
     679             :     }
     680         156 : }
     681             : 
     682             : namespace {
     683             : 
     684             : class CategoryDimInserter : std::unary_function<long, void>
     685             : {
     686             :     ScDPSource& mrSource;
     687             :     boost::unordered_set<sal_Int32>& mrCatDims;
     688             : public:
     689         135 :     CategoryDimInserter(ScDPSource& rSource, boost::unordered_set<sal_Int32>& rCatDims) :
     690             :         mrSource(rSource),
     691         135 :         mrCatDims(rCatDims) {}
     692             : 
     693         536 :     void operator() (long nDim)
     694             :     {
     695         536 :         if (!mrSource.IsDataLayoutDimension(nDim))
     696         534 :             mrCatDims.insert(nDim);
     697         536 :     }
     698             : };
     699             : 
     700             : }
     701             : 
     702         135 : void ScDPSource::GetCategoryDimensionIndices(boost::unordered_set<sal_Int32>& rCatDims)
     703             : {
     704         135 :     boost::unordered_set<sal_Int32> aCatDims;
     705             : 
     706         135 :     CategoryDimInserter aInserter(*this, aCatDims);
     707         135 :     std::for_each(maColDims.begin(), maColDims.end(), aInserter);
     708         135 :     std::for_each(maRowDims.begin(), maRowDims.end(), aInserter);
     709         135 :     std::for_each(maPageDims.begin(), maPageDims.end(), aInserter);
     710             : 
     711         135 :     rCatDims.swap(aCatDims);
     712         135 : }
     713             : 
     714          78 : void ScDPSource::FilterCacheByPageDimensions()
     715             : {
     716             :     // #i117661# Repeated calls to ScDPFilteredCache::filterByPageDimension
     717             :     // are invalid because rows are only hidden, never shown again. If
     718             :     // FilterCacheByPageDimensions is called again, the cache table must
     719             :     // be re-initialized. Currently, CreateRes_Impl always uses a fresh cache
     720             :     // because ScDBDocFunc::DataPilotUpdate calls InvalidateData.
     721             : 
     722          78 :     if (bPageFiltered)
     723             :     {
     724             :         SAL_WARN( "sc.core","tried to apply page field filters several times");
     725             : 
     726           0 :         pData->DisposeData();
     727           0 :         pData->CreateCacheTable();  // re-initialize the cache table
     728           0 :         bPageFiltered = false;
     729             :     }
     730             : 
     731             :     // filter table by page dimensions.
     732          78 :     vector<ScDPFilteredCache::Criterion> aCriteria;
     733          78 :     vector<long>::const_iterator it = maPageDims.begin(), itEnd = maPageDims.end();
     734          99 :     for (; it != itEnd; ++it)
     735             :     {
     736          21 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     737          21 :         long nField = pDim->GetDimension();
     738             : 
     739          21 :         ScDPMembers* pMems = pDim->GetHierarchiesObject()->getByIndex(0)->
     740          21 :             GetLevelsObject()->getByIndex(0)->GetMembersObject();
     741             : 
     742          21 :         long nMemCount = pMems->getCount();
     743          21 :         ScDPFilteredCache::Criterion aFilter;
     744          21 :         aFilter.mnFieldIndex = static_cast<sal_Int32>(nField);
     745          21 :         aFilter.mpFilter.reset(new ScDPFilteredCache::GroupFilter);
     746             :         ScDPFilteredCache::GroupFilter* pGrpFilter =
     747          21 :             static_cast<ScDPFilteredCache::GroupFilter*>(aFilter.mpFilter.get());
     748         113 :         for (long j = 0; j < nMemCount; ++j)
     749             :         {
     750          92 :             ScDPMember* pMem = pMems->getByIndex(j);
     751          92 :             if (pMem->isVisible())
     752             :             {
     753          90 :                 ScDPItemData aData;
     754          90 :                 pMem->FillItemData(aData);
     755          90 :                 pGrpFilter->addMatchItem(aData);
     756             :             }
     757             :         }
     758          21 :         if (pGrpFilter->getMatchItemCount() < static_cast<size_t>(nMemCount))
     759             :             // there is at least one invisible item.  Add this filter criterion to the mix.
     760           2 :             aCriteria.push_back(aFilter);
     761             : 
     762          21 :         if (!pDim || !pDim->HasSelectedPage())
     763          21 :             continue;
     764             : 
     765           0 :         const ScDPItemData& rData = pDim->GetSelectedData();
     766           0 :         aCriteria.push_back(ScDPFilteredCache::Criterion());
     767           0 :         ScDPFilteredCache::Criterion& r = aCriteria.back();
     768           0 :         r.mnFieldIndex = static_cast<sal_Int32>(nField);
     769           0 :         r.mpFilter.reset(new ScDPFilteredCache::SingleFilter(rData));
     770           0 :     }
     771          78 :     if (!aCriteria.empty())
     772             :     {
     773           2 :         boost::unordered_set<sal_Int32> aCatDims;
     774           2 :         GetCategoryDimensionIndices(aCatDims);
     775           2 :         pData->FilterCacheTable(aCriteria, aCatDims);
     776           2 :         bPageFiltered = true;
     777          78 :     }
     778          78 : }
     779             : 
     780         222 : void ScDPSource::CreateRes_Impl()
     781             : {
     782         222 :     if (pResData)
     783         288 :         return;
     784             : 
     785          78 :     sal_uInt16 nDataOrient = GetDataLayoutOrientation();
     786          78 :     if (maDataDims.size() > 1 && ( nDataOrient != sheet::DataPilotFieldOrientation_COLUMN &&
     787             :                                 nDataOrient != sheet::DataPilotFieldOrientation_ROW ) )
     788             :     {
     789             :         //  if more than one data dimension, data layout orientation must be set
     790           0 :         SetOrientation( pData->GetColumnCount(), sheet::DataPilotFieldOrientation_ROW );
     791           0 :         nDataOrient = sheet::DataPilotFieldOrientation_ROW;
     792             :     }
     793             : 
     794             :     // TODO: Aggreate pDataNames, pDataRefValues, nDataRefOrient, and
     795             :     // eDataFunctions into a structure and use vector instead of static
     796             :     // or pointer arrays.
     797          78 :     vector<OUString> aDataNames;
     798         156 :     vector<sheet::DataPilotFieldReference> aDataRefValues;
     799         156 :     vector<ScSubTotalFunc> aDataFunctions;
     800         156 :     vector<sal_uInt16> aDataRefOrient;
     801             : 
     802         156 :     ScDPTableData::CalcInfo aInfo;
     803             : 
     804             : 
     805             :     //  LateInit (initialize only those rows/children that are used) can be used unless
     806             :     //  any data dimension needs reference values from column/row dimensions
     807          78 :     bool bLateInit = true;
     808             : 
     809             :     // Go through all data dimensions (i.e. fields) and build their meta data
     810             :     // so that they can be passed on to ScDPResultData instance later.
     811             :     // TODO: aggregate all of data dimension info into a structure.
     812          78 :     vector<long>::const_iterator it = maDataDims.begin(), itEnd = maDataDims.end();
     813         152 :     for (; it != itEnd; ++it)
     814             :     {
     815             :         // Get function for each data field.
     816          74 :         long nDimIndex = *it;
     817          74 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(nDimIndex);
     818          74 :         sheet::GeneralFunction eUser = (sheet::GeneralFunction)pDim->getFunction();
     819          74 :         if (eUser == sheet::GeneralFunction_AUTO)
     820             :         {
     821             :             //! test for numeric data
     822          27 :             eUser = sheet::GeneralFunction_SUM;
     823             :         }
     824             : 
     825             :         // Map UNO's enum to internal enum ScSubTotalFunc.
     826          74 :         aDataFunctions.push_back(ScDataUnoConversion::GeneralToSubTotal(eUser));
     827             : 
     828             :         // Get reference field/item information.
     829          74 :         aDataRefValues.push_back(pDim->GetReferenceValue());
     830          74 :         sal_uInt16 nDataRefOrient = sheet::DataPilotFieldOrientation_HIDDEN;    // default if not used
     831          74 :         sal_Int32 eRefType = aDataRefValues.back().ReferenceType;
     832          74 :         if ( eRefType == sheet::DataPilotFieldReferenceType::ITEM_DIFFERENCE ||
     833          72 :              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE ||
     834          71 :              eRefType == sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE ||
     835             :              eRefType == sheet::DataPilotFieldReferenceType::RUNNING_TOTAL )
     836             :         {
     837             :             long nColumn = lcl_GetIndexFromName(
     838           4 :                 aDataRefValues.back().ReferenceField, GetDimensionsObject()->getElementNames());
     839           4 :             if ( nColumn >= 0 )
     840             :             {
     841           4 :                 nDataRefOrient = GetOrientation(nColumn);
     842             :                 //  need fully initialized results to find reference values
     843             :                 //  (both in column or row dimensions), so updated values or
     844             :                 //  differences to 0 can be displayed even for empty results.
     845           4 :                 bLateInit = false;
     846             :             }
     847             :         }
     848             : 
     849          74 :         aDataRefOrient.push_back(nDataRefOrient);
     850             : 
     851          74 :         aDataNames.push_back(pDim->getName());
     852             : 
     853             :         //! modify user visible strings as in ScDPResultData::GetMeasureString instead!
     854             : 
     855          74 :         aDataNames.back() = ScDPUtil::getSourceDimensionName(aDataNames.back());
     856             : 
     857             :         //! if the name is overridden by user, a flag must be set
     858             :         //! so the user defined name replaces the function string and field name.
     859             : 
     860             :         //! the complete name (function and field) must be stored at the dimension
     861             : 
     862          74 :         long nSource = pDim->GetSourceDim();
     863          74 :         if (nSource >= 0)
     864           2 :             aInfo.aDataSrcCols.push_back(nSource);
     865             :         else
     866          72 :             aInfo.aDataSrcCols.push_back(nDimIndex);
     867             :     }
     868             : 
     869          78 :     pResData = new ScDPResultData(*this);
     870          78 :     pResData->SetMeasureData(aDataFunctions, aDataRefValues, aDataRefOrient, aDataNames);
     871          78 :     pResData->SetDataLayoutOrientation(nDataOrient);
     872          78 :     pResData->SetLateInit( bLateInit );
     873             : 
     874          78 :     bool bHasAutoShow = false;
     875             : 
     876         156 :     ScDPInitState aInitState;
     877             : 
     878             :     // Page field selections restrict the members shown in related fields
     879             :     // (both in column and row fields). aInitState is filled with the page
     880             :     // field selections, they are kept across the data iterator loop.
     881             : 
     882          99 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     883             :     {
     884          21 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     885          21 :         if ( pDim->HasSelectedPage() )
     886           0 :             aInitState.AddMember(*it, GetMemberId(*it, pDim->GetSelectedData()));
     887             :     }
     888             : 
     889             :     // Show grand total columns only when the option is set *and* there is at
     890             :     // least one column field.  Same for the grand total rows.
     891          78 :     sal_uInt16 nDataLayoutOrient = GetDataLayoutOrientation();
     892          78 :     long nColDimCount2 = maColDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_COLUMN ? 1 : 0);
     893          78 :     long nRowDimCount2 = maRowDims.size() - (nDataLayoutOrient == sheet::DataPilotFieldOrientation_ROW ? 1 : 0);
     894          78 :     bool bShowColGrand = bColumnGrand && nColDimCount2 > 0;
     895          78 :     bool bShowRowGrand = bRowGrand && nRowDimCount2 > 0;
     896          78 :     pColResRoot = new ScDPResultMember(pResData, bShowColGrand);
     897          78 :     pRowResRoot = new ScDPResultMember(pResData, bShowRowGrand);
     898             : 
     899          78 :     FillCalcInfo(false, aInfo, bHasAutoShow);
     900          78 :     long nColLevelCount = aInfo.aColLevels.size();
     901             : 
     902          78 :     pColResRoot->InitFrom( aInfo.aColDims, aInfo.aColLevels, 0, aInitState );
     903          78 :     pColResRoot->SetHasElements();
     904             : 
     905          78 :     FillCalcInfo(true, aInfo, bHasAutoShow);
     906          78 :     long nRowLevelCount = aInfo.aRowLevels.size();
     907             : 
     908          78 :     if ( nRowLevelCount > 0 )
     909             :     {
     910             :         // disable layout flags for the innermost row field (level)
     911          64 :         aInfo.aRowLevels[nRowLevelCount-1]->SetEnableLayout( false );
     912             :     }
     913             : 
     914          78 :     pRowResRoot->InitFrom( aInfo.aRowDims, aInfo.aRowLevels, 0, aInitState );
     915          78 :     pRowResRoot->SetHasElements();
     916             : 
     917             :     // initialize members object also for all page dimensions (needed for numeric groups)
     918          99 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     919             :     {
     920          21 :         ScDPDimension* pDim = GetDimensionsObject()->getByIndex(*it);
     921          21 :         long nHierarchy = pDim->getUsedHierarchy();
     922          21 :         if ( nHierarchy >= pDim->GetHierarchiesObject()->getCount() )
     923           0 :             nHierarchy = 0;
     924             : 
     925          21 :         ScDPLevels* pLevels = pDim->GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
     926          21 :         long nCount = pLevels->getCount();
     927          42 :         for (long j=0; j<nCount; j++)
     928          21 :             pLevels->getByIndex(j)->GetMembersObject();             // initialize for groups
     929             :     }
     930             : 
     931             :     //  pre-check: calculate minimum number of result columns / rows from
     932             :     //  levels that have the "show all" flag set
     933             : 
     934          78 :     long nMinColMembers = lcl_CountMinMembers( aInfo.aColDims, aInfo.aColLevels, nColLevelCount );
     935          78 :     long nMinRowMembers = lcl_CountMinMembers( aInfo.aRowDims, aInfo.aRowLevels, nRowLevelCount );
     936             : 
     937          78 :     if ( nMinColMembers > MAXCOLCOUNT/*SC_MINCOUNT_LIMIT*/ || nMinRowMembers > SC_MINCOUNT_LIMIT )
     938             :     {
     939             :         //  resulting table is too big -> abort before calculating
     940             :         //  (this relies on late init, so no members are allocated in InitFrom above)
     941             : 
     942           0 :         bResultOverflow = true;
     943           0 :         return;
     944             :     }
     945             : 
     946          78 :     FilterCacheByPageDimensions();
     947             : 
     948          78 :     aInfo.aPageDims.reserve(maPageDims.size());
     949          99 :     for (it = maPageDims.begin(), itEnd = maPageDims.end(); it != itEnd; ++it)
     950          21 :         aInfo.aPageDims.push_back(*it);
     951             : 
     952          78 :     aInfo.pInitState = &aInitState;
     953          78 :     aInfo.pColRoot   = pColResRoot;
     954          78 :     aInfo.pRowRoot   = pRowResRoot;
     955          78 :     pData->CalcResults(aInfo, false);
     956             : 
     957          78 :     pColResRoot->CheckShowEmpty();
     958          78 :     pRowResRoot->CheckShowEmpty();
     959             :     // ----------------------------------------------------------------
     960             :     //  With all data processed, calculate the final results:
     961             : 
     962             :     //  UpdateDataResults calculates all original results from the collected values,
     963             :     //  and stores them as reference values if needed.
     964          78 :     pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
     965             : 
     966          78 :     if ( bHasAutoShow )     // do the double calculation only if AutoShow is used
     967             :     {
     968             :         //  Find the desired members and set bAutoHidden flag for the others
     969           1 :         pRowResRoot->DoAutoShow( pColResRoot );
     970             : 
     971             :         //  Reset all results to empty, so they can be built again with data for the
     972             :         //  desired members only.
     973           1 :         pColResRoot->ResetResults();
     974           1 :         pRowResRoot->ResetResults();
     975           1 :         pData->CalcResults(aInfo, true);
     976             : 
     977             :         //  Call UpdateDataResults again, with the new (limited) values.
     978           1 :         pRowResRoot->UpdateDataResults( pColResRoot, pResData->GetRowStartMeasure() );
     979             :     }
     980             : 
     981             :     //  SortMembers does the sorting by a result dimension, using the orginal results,
     982             :     //  but not running totals etc.
     983          78 :     pRowResRoot->SortMembers( pColResRoot );
     984             : 
     985             :     //  UpdateRunningTotals calculates running totals along column/row dimensions,
     986             :     //  differences from other members (named or relative), and column/row percentages
     987             :     //  or index values.
     988             :     //  Running totals and relative differences need to be done using the sorted values.
     989             :     //  Column/row percentages and index values must be done after sorting, because the
     990             :     //  results may no longer be in the right order (row total for percentage of row is
     991             :     //  always 1).
     992         156 :     ScDPRunningTotalState aRunning( pColResRoot, pRowResRoot );
     993         156 :     ScDPRowTotals aTotals;
     994         156 :     pRowResRoot->UpdateRunningTotals( pColResRoot, pResData->GetRowStartMeasure(), aRunning, aTotals );
     995             : }
     996             : 
     997             : 
     998         132 : void ScDPSource::FillLevelList( sal_uInt16 nOrientation, std::vector<ScDPLevel*> &rList )
     999             : {
    1000         132 :     rList.clear();
    1001             : 
    1002         132 :     std::vector<long>* pDimIndex = NULL;
    1003         132 :     switch (nOrientation)
    1004             :     {
    1005             :         case sheet::DataPilotFieldOrientation_COLUMN:
    1006          66 :             pDimIndex = &maColDims;
    1007          66 :             break;
    1008             :         case sheet::DataPilotFieldOrientation_ROW:
    1009          66 :             pDimIndex = &maRowDims;
    1010          66 :             break;
    1011             :         case sheet::DataPilotFieldOrientation_DATA:
    1012           0 :             pDimIndex = &maDataDims;
    1013           0 :             break;
    1014             :         case sheet::DataPilotFieldOrientation_PAGE:
    1015           0 :             pDimIndex = &maPageDims;
    1016           0 :             break;
    1017             :         default:
    1018             :             OSL_FAIL( "ScDPSource::FillLevelList: unexpected orientation" );
    1019           0 :             break;
    1020             :     }
    1021         132 :     if (!pDimIndex)
    1022             :     {
    1023             :         OSL_FAIL("invalid orientation");
    1024         132 :         return;
    1025             :     }
    1026             : 
    1027         132 :     ScDPDimensions* pDims = GetDimensionsObject();
    1028         132 :     std::vector<long>::const_iterator it = pDimIndex->begin(), itEnd = pDimIndex->end();
    1029         289 :     for (; it != itEnd; ++it)
    1030             :     {
    1031         157 :         ScDPDimension* pDim = pDims->getByIndex(*it);
    1032             :         OSL_ENSURE( pDim->getOrientation() == nOrientation, "orientations are wrong" );
    1033             : 
    1034         157 :         ScDPHierarchies* pHiers = pDim->GetHierarchiesObject();
    1035         157 :         long nHierarchy = pDim->getUsedHierarchy();
    1036         157 :         if ( nHierarchy >= pHiers->getCount() )
    1037           0 :             nHierarchy = 0;
    1038         157 :         ScDPHierarchy* pHier = pHiers->getByIndex(nHierarchy);
    1039         157 :         ScDPLevels* pLevels = pHier->GetLevelsObject();
    1040         157 :         long nLevCount = pLevels->getCount();
    1041         314 :         for (long nLev=0; nLev<nLevCount; nLev++)
    1042             :         {
    1043         157 :             ScDPLevel* pLevel = pLevels->getByIndex(nLev);
    1044         157 :             rList.push_back(pLevel);
    1045             :         }
    1046             :     }
    1047             : }
    1048             : 
    1049         198 : void ScDPSource::FillMemberResults()
    1050             : {
    1051         198 :     if ( !pColResults && !pRowResults )
    1052             :     {
    1053          66 :         CreateRes_Impl();
    1054             : 
    1055          66 :         if ( bResultOverflow )      // set in CreateRes_Impl
    1056             :         {
    1057             :             //  no results available -> abort (leave empty)
    1058             :             //  exception is thrown in ScDPSource::getResults
    1059         198 :             return;
    1060             :         }
    1061             : 
    1062          66 :         FillLevelList( sheet::DataPilotFieldOrientation_COLUMN, aColLevelList );
    1063          66 :         long nColLevelCount = aColLevelList.size();
    1064          66 :         if (nColLevelCount)
    1065             :         {
    1066          41 :             long nColDimSize = pColResRoot->GetSize(pResData->GetColStartMeasure());
    1067          41 :             pColResults = new uno::Sequence<sheet::MemberResult>[nColLevelCount];
    1068          86 :             for (long i=0; i<nColLevelCount; i++)
    1069          45 :                 pColResults[i].realloc(nColDimSize);
    1070             : 
    1071          41 :             long nPos = 0;
    1072             :             pColResRoot->FillMemberResults( pColResults, nPos, pResData->GetColStartMeasure(),
    1073          41 :                                             sal_True, NULL, NULL );
    1074             :         }
    1075             : 
    1076          66 :         FillLevelList( sheet::DataPilotFieldOrientation_ROW, aRowLevelList );
    1077          66 :         long nRowLevelCount = aRowLevelList.size();
    1078          66 :         if (nRowLevelCount)
    1079             :         {
    1080          64 :             long nRowDimSize = pRowResRoot->GetSize(pResData->GetRowStartMeasure());
    1081          64 :             pRowResults = new uno::Sequence<sheet::MemberResult>[nRowLevelCount];
    1082         176 :             for (long i=0; i<nRowLevelCount; i++)
    1083         112 :                 pRowResults[i].realloc(nRowDimSize);
    1084             : 
    1085          64 :             long nPos = 0;
    1086             :             pRowResRoot->FillMemberResults( pRowResults, nPos, pResData->GetRowStartMeasure(),
    1087          64 :                                             sal_True, NULL, NULL );
    1088             :         }
    1089             :     }
    1090             : }
    1091             : 
    1092         198 : const uno::Sequence<sheet::MemberResult>* ScDPSource::GetMemberResults( ScDPLevel* pLevel )
    1093             : {
    1094         198 :     FillMemberResults();
    1095             : 
    1096         198 :     long i = 0;
    1097         198 :     long nColCount = aColLevelList.size();
    1098         286 :     for (i=0; i<nColCount; i++)
    1099             :     {
    1100         134 :         ScDPLevel* pColLevel = aColLevelList[i];
    1101         134 :         if ( pColLevel == pLevel )
    1102          46 :             return pColResults+i;
    1103             :     }
    1104         152 :     long nRowCount = aRowLevelList.size();
    1105         250 :     for (i=0; i<nRowCount; i++)
    1106             :     {
    1107         250 :         ScDPLevel* pRowLevel = aRowLevelList[i];
    1108         250 :         if ( pRowLevel == pLevel )
    1109         152 :             return pRowResults+i;
    1110             :     }
    1111           0 :     return NULL;
    1112             : }
    1113             : 
    1114             : // XPropertySet
    1115             : 
    1116           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPSource::getPropertySetInfo()
    1117             :                                                         throw(uno::RuntimeException)
    1118             : {
    1119           0 :     SolarMutexGuard aGuard;
    1120             :     using beans::PropertyAttribute::READONLY;
    1121             : 
    1122             :     static SfxItemPropertyMapEntry aDPSourceMap_Impl[] =
    1123             :     {
    1124           0 :         {MAP_CHAR_LEN(SC_UNO_DP_COLGRAND), 0,  &getBooleanCppuType(),              0, 0 },
    1125           0 :         {MAP_CHAR_LEN(SC_UNO_DP_DATADESC), 0,  &getCppuType((OUString*)0),    beans::PropertyAttribute::READONLY, 0 },
    1126           0 :         {MAP_CHAR_LEN(SC_UNO_DP_IGNOREEMPTY), 0,  &getBooleanCppuType(),              0, 0 },     // for sheet data only
    1127           0 :         {MAP_CHAR_LEN(SC_UNO_DP_REPEATEMPTY), 0,  &getBooleanCppuType(),              0, 0 },     // for sheet data only
    1128           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ROWGRAND), 0,  &getBooleanCppuType(),              0, 0 },
    1129           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ROWFIELDCOUNT),    0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
    1130           0 :         {MAP_CHAR_LEN(SC_UNO_DP_COLUMNFIELDCOUNT), 0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
    1131           0 :         {MAP_CHAR_LEN(SC_UNO_DP_DATAFIELDCOUNT),   0, &getCppuType(static_cast<sal_Int32*>(0)), READONLY, 0 },
    1132           0 :         {MAP_CHAR_LEN(SC_UNO_DP_GRANDTOTAL_NAME),  0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
    1133             :         {0,0,0,0,0,0}
    1134           0 :     };
    1135             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    1136           0 :         new SfxItemPropertySetInfo( aDPSourceMap_Impl );
    1137           0 :     return aRef;
    1138             : }
    1139             : 
    1140         440 : void SAL_CALL ScDPSource::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    1141             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    1142             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    1143             :                         uno::RuntimeException)
    1144             : {
    1145         440 :     if (aPropertyName.equalsAscii(SC_UNO_DP_COLGRAND))
    1146         110 :         bColumnGrand = lcl_GetBoolFromAny(aValue);
    1147         330 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_ROWGRAND))
    1148         110 :         bRowGrand = lcl_GetBoolFromAny(aValue);
    1149         220 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_IGNOREEMPTY))
    1150         110 :         setIgnoreEmptyRows( lcl_GetBoolFromAny( aValue ) );
    1151         110 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_REPEATEMPTY))
    1152         110 :         setRepeatIfEmpty( lcl_GetBoolFromAny( aValue ) );
    1153           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
    1154             :     {
    1155           0 :         OUString aName;
    1156           0 :         if (aValue >>= aName)
    1157           0 :             mpGrandTotalName.reset(new OUString(aName));
    1158             :     }
    1159             :     else
    1160             :     {
    1161             :         OSL_FAIL("unknown property");
    1162             :         //! THROW( UnknownPropertyException() );
    1163             :     }
    1164         440 : }
    1165             : 
    1166        1253 : uno::Any SAL_CALL ScDPSource::getPropertyValue( const OUString& aPropertyName )
    1167             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    1168             :                         uno::RuntimeException)
    1169             : {
    1170        1253 :     uno::Any aRet;
    1171        1253 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_COLGRAND ) )
    1172         327 :         lcl_SetBoolInAny(aRet, bColumnGrand);
    1173         926 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWGRAND ) )
    1174         327 :         lcl_SetBoolInAny(aRet, bRowGrand);
    1175         599 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_IGNOREEMPTY ) )
    1176           0 :         lcl_SetBoolInAny(aRet, bIgnoreEmptyRows);
    1177         599 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REPEATEMPTY ) )
    1178           0 :         lcl_SetBoolInAny(aRet, bRepeatIfEmpty);
    1179         599 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATADESC ) )             // read-only
    1180          78 :         aRet <<= getDataDescription();
    1181         521 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ROWFIELDCOUNT ) )        // read-only
    1182           0 :         aRet <<= static_cast<sal_Int32>(maRowDims.size());
    1183         521 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_COLUMNFIELDCOUNT ) )     // read-only
    1184           0 :         aRet <<= static_cast<sal_Int32>(maColDims.size());
    1185         521 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_DATAFIELDCOUNT ) )       // read-only
    1186         521 :         aRet <<= static_cast<sal_Int32>(maDataDims.size());
    1187           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_GRANDTOTAL_NAME))
    1188             :     {
    1189           0 :         if (mpGrandTotalName.get())
    1190           0 :             aRet <<= *mpGrandTotalName;
    1191             :     }
    1192             :     else
    1193             :     {
    1194             :         OSL_FAIL("unknown property");
    1195             :         //! THROW( UnknownPropertyException() );
    1196             :     }
    1197        1253 :     return aRet;
    1198             : }
    1199             : 
    1200             : #if DEBUG_PIVOT_TABLE
    1201             : void ScDPSource::DumpResults() const
    1202             : {
    1203             :     std::cout << "+++++ column root" << std::endl;
    1204             :     pColResRoot->Dump(1);
    1205             :     std::cout << "+++++ row root" << std::endl;
    1206             :     pRowResRoot->Dump(1);
    1207             : }
    1208             : #endif
    1209             : 
    1210           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPSource )
    1211             : 
    1212             : // -----------------------------------------------------------------------
    1213             : 
    1214         110 : ScDPDimensions::ScDPDimensions( ScDPSource* pSrc ) :
    1215             :     pSource( pSrc ),
    1216         110 :     ppDims( NULL )
    1217             : {
    1218             :     //! hold pSource
    1219             : 
    1220             :     // include data layout dimension and duplicated dimensions
    1221         110 :     nDimCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
    1222         110 : }
    1223             : 
    1224         330 : ScDPDimensions::~ScDPDimensions()
    1225             : {
    1226             :     //! release pSource
    1227             : 
    1228         110 :     if (ppDims)
    1229             :     {
    1230         617 :         for (long i=0; i<nDimCount; i++)
    1231         507 :             if ( ppDims[i] )
    1232         507 :                 ppDims[i]->release();           // ref-counted
    1233         110 :         delete[] ppDims;
    1234             :     }
    1235         220 : }
    1236             : 
    1237           2 : void ScDPDimensions::CountChanged()
    1238             : {
    1239             :     // include data layout dimension and duplicated dimensions
    1240           2 :     long nNewCount = pSource->GetData()->GetColumnCount() + 1 + pSource->GetDupCount();
    1241           2 :     if ( ppDims )
    1242             :     {
    1243             :         long i;
    1244           2 :         long nCopy = std::min( nNewCount, nDimCount );
    1245           2 :         ScDPDimension** ppNew = new ScDPDimension*[nNewCount];
    1246             : 
    1247           8 :         for (i=0; i<nCopy; i++)             // copy existing dims
    1248           6 :             ppNew[i] = ppDims[i];
    1249           4 :         for (i=nCopy; i<nNewCount; i++)     // clear additional pointers
    1250           2 :             ppNew[i] = NULL;
    1251           2 :         for (i=nCopy; i<nDimCount; i++)     // delete old dims if count is decreased
    1252           0 :             if ( ppDims[i] )
    1253           0 :                 ppDims[i]->release();       // ref-counted
    1254             : 
    1255           2 :         delete[] ppDims;
    1256           2 :         ppDims = ppNew;
    1257             :     }
    1258           2 :     nDimCount = nNewCount;
    1259           2 : }
    1260             : 
    1261             : // very simple XNameAccess implementation using getCount/getByIndex
    1262             : 
    1263        5014 : uno::Any SAL_CALL ScDPDimensions::getByName( const OUString& aName )
    1264             :             throw(container::NoSuchElementException,
    1265             :                     lang::WrappedTargetException, uno::RuntimeException)
    1266             : {
    1267        5014 :     long nCount = getCount();
    1268       15268 :     for (long i=0; i<nCount; i++)
    1269       15268 :         if ( getByIndex(i)->getName() == aName )
    1270             :         {
    1271        5014 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1272       10028 :             uno::Any aRet;
    1273        5014 :             aRet <<= xNamed;
    1274       15042 :             return aRet;
    1275             :         }
    1276             : 
    1277           0 :     throw container::NoSuchElementException();
    1278             : //    return uno::Any();
    1279             : }
    1280             : 
    1281        1062 : uno::Sequence<OUString> SAL_CALL ScDPDimensions::getElementNames() throw(uno::RuntimeException)
    1282             : {
    1283        1062 :     long nCount = getCount();
    1284        1062 :     uno::Sequence<OUString> aSeq(nCount);
    1285        1062 :     OUString* pArr = aSeq.getArray();
    1286        7052 :     for (long i=0; i<nCount; i++)
    1287        5990 :         pArr[i] = getByIndex(i)->getName();
    1288        1062 :     return aSeq;
    1289             : }
    1290             : 
    1291           0 : sal_Bool SAL_CALL ScDPDimensions::hasByName( const OUString& aName ) throw(uno::RuntimeException)
    1292             : {
    1293           0 :     long nCount = getCount();
    1294           0 :     for (long i=0; i<nCount; i++)
    1295           0 :         if ( getByIndex(i)->getName() == aName )
    1296           0 :             return sal_True;
    1297           0 :     return false;
    1298             : }
    1299             : 
    1300           0 : uno::Type SAL_CALL ScDPDimensions::getElementType() throw(uno::RuntimeException)
    1301             : {
    1302           0 :     return getCppuType((uno::Reference<container::XNamed>*)0);
    1303             : }
    1304             : 
    1305           0 : sal_Bool SAL_CALL ScDPDimensions::hasElements() throw(uno::RuntimeException)
    1306             : {
    1307           0 :     return ( getCount() > 0 );
    1308             : }
    1309             : 
    1310             : // end of XNameAccess implementation
    1311             : 
    1312        6096 : long ScDPDimensions::getCount() const
    1313             : {
    1314             :     //  in tabular data, every column of source data is a dimension
    1315             : 
    1316        6096 :     return nDimCount;
    1317             : }
    1318             : 
    1319       29604 : ScDPDimension* ScDPDimensions::getByIndex(long nIndex) const
    1320             : {
    1321       29604 :     if ( nIndex >= 0 && nIndex < nDimCount )
    1322             :     {
    1323       29604 :         if ( !ppDims )
    1324             :         {
    1325         110 :             ((ScDPDimensions*)this)->ppDims = new ScDPDimension*[nDimCount];
    1326         615 :             for (long i=0; i<nDimCount; i++)
    1327         505 :                 ppDims[i] = NULL;
    1328             :         }
    1329       29604 :         if ( !ppDims[nIndex] )
    1330             :         {
    1331         507 :             ppDims[nIndex] = new ScDPDimension( pSource, nIndex );
    1332         507 :             ppDims[nIndex]->acquire();      // ref-counted
    1333             :         }
    1334             : 
    1335       29604 :         return ppDims[nIndex];
    1336             :     }
    1337             : 
    1338           0 :     return NULL;    //! exception?
    1339             : }
    1340             : 
    1341             : // -----------------------------------------------------------------------
    1342             : 
    1343         507 : ScDPDimension::ScDPDimension( ScDPSource* pSrc, long nD ) :
    1344             :     pSource( pSrc ),
    1345             :     nDim( nD ),
    1346             :     pHierarchies( NULL ),
    1347             :     nUsedHier( 0 ),
    1348             :     nFunction( SUBTOTAL_FUNC_SUM ),     // sum is default
    1349             :     mpLayoutName(NULL),
    1350             :     mpSubtotalName(NULL),
    1351             :     nSourceDim( -1 ),
    1352             :     bHasSelectedPage( false ),
    1353             :     pSelectedData( NULL ),
    1354         507 :     mbHasHiddenMember(false)
    1355             : {
    1356             :     //! hold pSource
    1357         507 : }
    1358             : 
    1359        1521 : ScDPDimension::~ScDPDimension()
    1360             : {
    1361             :     //! release pSource
    1362             : 
    1363         507 :     if ( pHierarchies )
    1364         279 :         pHierarchies->release();    // ref-counted
    1365             : 
    1366         507 :     delete pSelectedData;
    1367        1014 : }
    1368             : 
    1369        2202 : ScDPHierarchies* ScDPDimension::GetHierarchiesObject()
    1370             : {
    1371        2202 :     if (!pHierarchies)
    1372             :     {
    1373         279 :         pHierarchies = new ScDPHierarchies( pSource, nDim );
    1374         279 :         pHierarchies->acquire();        // ref-counted
    1375             :     }
    1376        2202 :     return pHierarchies;
    1377             : }
    1378             : 
    1379         330 : const OUString* ScDPDimension::GetLayoutName() const
    1380             : {
    1381         330 :     return mpLayoutName.get();
    1382             : }
    1383             : 
    1384           0 : const OUString* ScDPDimension::GetSubtotalName() const
    1385             : {
    1386           0 :     return mpSubtotalName.get();
    1387             : }
    1388             : 
    1389         596 : uno::Reference<container::XNameAccess> SAL_CALL ScDPDimension::getHierarchies()
    1390             :                                                     throw(uno::RuntimeException)
    1391             : {
    1392         596 :     return GetHierarchiesObject();
    1393             : }
    1394             : 
    1395       24095 : OUString SAL_CALL ScDPDimension::getName() throw(uno::RuntimeException)
    1396             : {
    1397       24095 :     if (!aName.isEmpty())
    1398          26 :         return aName;
    1399             :     else
    1400       24069 :         return pSource->GetData()->getDimensionName( nDim );
    1401             : }
    1402             : 
    1403           2 : void SAL_CALL ScDPDimension::setName( const OUString& rNewName ) throw(uno::RuntimeException)
    1404             : {
    1405             :     //  used after cloning
    1406           2 :     aName = rNewName;
    1407           2 : }
    1408             : 
    1409        2930 : sal_uInt16 ScDPDimension::getOrientation() const
    1410             : {
    1411        2930 :     return pSource->GetOrientation( nDim );
    1412             : }
    1413             : 
    1414         780 : void ScDPDimension::setOrientation(sal_uInt16 nNew)
    1415             : {
    1416         780 :     pSource->SetOrientation( nDim, nNew );
    1417         780 : }
    1418             : 
    1419         400 : long ScDPDimension::getPosition() const
    1420             : {
    1421         400 :     return pSource->GetPosition( nDim );
    1422             : }
    1423             : 
    1424        3172 : bool ScDPDimension::getIsDataLayoutDimension() const
    1425             : {
    1426        3172 :     return pSource->GetData()->getIsDataLayoutDimension( nDim );
    1427             : }
    1428             : 
    1429         955 : sal_uInt16 ScDPDimension::getFunction() const
    1430             : {
    1431         955 :     return nFunction;
    1432             : }
    1433             : 
    1434         275 : void ScDPDimension::setFunction(sal_uInt16 nNew)
    1435             : {
    1436         275 :     nFunction = nNew;
    1437         275 : }
    1438             : 
    1439         653 : long ScDPDimension::getUsedHierarchy() const
    1440             : {
    1441         653 :     return nUsedHier;
    1442             : }
    1443             : 
    1444         124 : void ScDPDimension::setUsedHierarchy(long /* nNew */)
    1445             : {
    1446             :     // #i52547# don't use the incomplete date hierarchy implementation - ignore the call
    1447         124 : }
    1448             : 
    1449           2 : ScDPDimension* ScDPDimension::CreateCloneObject()
    1450             : {
    1451             :     OSL_ENSURE( nSourceDim < 0, "recursive duplicate - not implemented" );
    1452             : 
    1453             :     //! set new name here, or temporary name ???
    1454           2 :     OUString aNewName = aName;
    1455             : 
    1456           2 :     ScDPDimension* pNew = pSource->AddDuplicated( nDim, aNewName );
    1457             : 
    1458           2 :     pNew->aName = aNewName;             //! here or in source?
    1459           2 :     pNew->nSourceDim = nDim;            //! recursive?
    1460             : 
    1461           2 :     return pNew;
    1462             : }
    1463             : 
    1464           2 : uno::Reference<util::XCloneable> SAL_CALL ScDPDimension::createClone() throw(uno::RuntimeException)
    1465             : {
    1466           2 :     return CreateCloneObject();
    1467             : }
    1468             : 
    1469          74 : const sheet::DataPilotFieldReference& ScDPDimension::GetReferenceValue() const
    1470             : {
    1471          74 :     return aReferenceValue;
    1472             : }
    1473             : 
    1474           0 : const ScDPItemData& ScDPDimension::GetSelectedData()
    1475             : {
    1476           0 :     if ( !pSelectedData )
    1477             :     {
    1478             :         // find the named member to initialize pSelectedData from it, with name and value
    1479             : 
    1480           0 :         long nLevel = 0;
    1481             : 
    1482           0 :         long nHierarchy = getUsedHierarchy();
    1483           0 :         if ( nHierarchy >= GetHierarchiesObject()->getCount() )
    1484           0 :             nHierarchy = 0;
    1485           0 :         ScDPLevels* pLevels = GetHierarchiesObject()->getByIndex(nHierarchy)->GetLevelsObject();
    1486           0 :         long nLevCount = pLevels->getCount();
    1487           0 :         if ( nLevel < nLevCount )
    1488             :         {
    1489           0 :             ScDPMembers* pMembers = pLevels->getByIndex(nLevel)->GetMembersObject();
    1490             : 
    1491             :             //! merge with ScDPMembers::getByName
    1492           0 :             long nCount = pMembers->getCount();
    1493           0 :             for (long i=0; i<nCount && !pSelectedData; i++)
    1494             :             {
    1495           0 :                 ScDPMember* pMember = pMembers->getByIndex(i);
    1496           0 :                 if (aSelectedPage.equals(pMember->GetNameStr()))
    1497             :                 {
    1498           0 :                     pSelectedData = new ScDPItemData();
    1499           0 :                     pMember->FillItemData( *pSelectedData );
    1500             :                 }
    1501             :             }
    1502             :         }
    1503             : 
    1504           0 :         if ( !pSelectedData )
    1505           0 :             pSelectedData = new ScDPItemData(aSelectedPage);      // default - name only
    1506             :     }
    1507             : 
    1508           0 :     return *pSelectedData;
    1509             : }
    1510             : 
    1511             : // XPropertySet
    1512             : 
    1513           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPDimension::getPropertySetInfo()
    1514             :                                                         throw(uno::RuntimeException)
    1515             : {
    1516           0 :     SolarMutexGuard aGuard;
    1517             : 
    1518             :     static SfxItemPropertyMapEntry aDPDimensionMap_Impl[] =
    1519             :     {
    1520           0 :         {MAP_CHAR_LEN(SC_UNO_DP_FILTER),   0,  &getCppuType((uno::Sequence<sheet::TableFilterField>*)0), 0, 0 },
    1521           0 :         {MAP_CHAR_LEN(SC_UNO_DP_FLAGS),    0,  &getCppuType((sal_Int32*)0),                beans::PropertyAttribute::READONLY, 0 },
    1522           0 :         {MAP_CHAR_LEN(SC_UNO_DP_FUNCTION), 0,  &getCppuType((sheet::GeneralFunction*)0),   0, 0 },
    1523           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ISDATALAYOUT), 0,  &getBooleanCppuType(),                      beans::PropertyAttribute::READONLY, 0 },
    1524           0 :         {MAP_CHAR_LEN(SC_UNO_DP_NUMBERFO), 0,  &getCppuType((sal_Int32*)0),                beans::PropertyAttribute::READONLY, 0 },
    1525           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ORIENTATION), 0,  &getCppuType((sheet::DataPilotFieldOrientation*)0), 0, 0 },
    1526           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL), 0,  &getCppuType((uno::Reference<container::XNamed>*)0), beans::PropertyAttribute::READONLY, 0 },
    1527           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ORIGINAL_POS), 0, &getCppuType((sal_Int32*)0),             0, 0 },
    1528           0 :         {MAP_CHAR_LEN(SC_UNO_DP_POSITION), 0,  &getCppuType((sal_Int32*)0),                0, 0 },
    1529           0 :         {MAP_CHAR_LEN(SC_UNO_DP_REFVALUE), 0,  &getCppuType((sheet::DataPilotFieldReference*)0), 0, 0 },
    1530           0 :         {MAP_CHAR_LEN(SC_UNO_DP_USEDHIERARCHY), 0,  &getCppuType((sal_Int32*)0),                0, 0 },
    1531           0 :         {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
    1532           0 :         {MAP_CHAR_LEN(SC_UNO_DP_FIELD_SUBTOTALNAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
    1533           0 :         {MAP_CHAR_LEN(SC_UNO_DP_HAS_HIDDEN_MEMBER), 0, &getBooleanCppuType(), 0, 0 },
    1534             :         {0,0,0,0,0,0}
    1535           0 :     };
    1536             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    1537           0 :         new SfxItemPropertySetInfo( aDPDimensionMap_Impl );
    1538           0 :     return aRef;
    1539             : }
    1540             : 
    1541        1460 : void SAL_CALL ScDPDimension::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    1542             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    1543             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    1544             :                         uno::RuntimeException)
    1545             : {
    1546        1460 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
    1547             :     {
    1548         124 :         sal_Int32 nInt = 0;
    1549         124 :         if (aValue >>= nInt)
    1550         124 :             setUsedHierarchy( nInt );
    1551             :     }
    1552        1336 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
    1553             :     {
    1554             :         sheet::DataPilotFieldOrientation eEnum;
    1555         780 :         if (aValue >>= eEnum)
    1556         780 :             setOrientation( sal::static_int_cast<sal_uInt16>(eEnum) );
    1557             :     }
    1558         556 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
    1559             :     {
    1560             :         sheet::GeneralFunction eEnum;
    1561         275 :         if (aValue >>= eEnum)
    1562         275 :             setFunction( sal::static_int_cast<sal_uInt16>(eEnum) );
    1563             :     }
    1564         281 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
    1565           6 :         aValue >>= aReferenceValue;
    1566         275 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
    1567             :     {
    1568           0 :         sal_Bool bDone = false;
    1569           0 :         uno::Sequence<sheet::TableFilterField> aSeq;
    1570           0 :         if (aValue >>= aSeq)
    1571             :         {
    1572           0 :             sal_Int32 nLength = aSeq.getLength();
    1573           0 :             if ( nLength == 0 )
    1574             :             {
    1575           0 :                 aSelectedPage = OUString();
    1576           0 :                 bHasSelectedPage = false;
    1577           0 :                 bDone = sal_True;
    1578             :             }
    1579           0 :             else if ( nLength == 1 )
    1580             :             {
    1581           0 :                 const sheet::TableFilterField& rField = aSeq[0];
    1582           0 :                 if ( rField.Field == 0 && rField.Operator == sheet::FilterOperator_EQUAL && !rField.IsNumeric )
    1583             :                 {
    1584           0 :                     aSelectedPage = rField.StringValue;
    1585           0 :                     bHasSelectedPage = true;
    1586           0 :                     bDone = sal_True;
    1587             :                 }
    1588             :             }
    1589             :         }
    1590           0 :         if ( !bDone )
    1591             :         {
    1592             :             OSL_FAIL("Filter property is not a single string");
    1593           0 :             throw lang::IllegalArgumentException();
    1594             :         }
    1595           0 :         DELETEZ( pSelectedData );       // invalid after changing aSelectedPage
    1596             :     }
    1597         275 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    1598             :     {
    1599           0 :         OUString aTmpName;
    1600           0 :         if (aValue >>= aTmpName)
    1601           0 :             mpLayoutName.reset(new OUString(aTmpName));
    1602             :     }
    1603         275 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
    1604             :     {
    1605           0 :         OUString aTmpName;
    1606           0 :         if (aValue >>= aTmpName)
    1607           0 :             mpSubtotalName.reset(new OUString(aTmpName));
    1608             :     }
    1609         275 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
    1610             :     {
    1611         275 :         sal_Bool b = false;
    1612         275 :         aValue >>= b;
    1613         275 :         mbHasHiddenMember = b;
    1614             :     }
    1615             :     else
    1616             :     {
    1617             :         OSL_FAIL("unknown property");
    1618             :         //! THROW( UnknownPropertyException() );
    1619             :     }
    1620        1460 : }
    1621             : 
    1622        8566 : uno::Any SAL_CALL ScDPDimension::getPropertyValue( const OUString& aPropertyName )
    1623             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    1624             :                         uno::RuntimeException)
    1625             : {
    1626        8566 :     uno::Any aRet;
    1627        8566 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    1628         400 :         aRet <<= (sal_Int32) getPosition();
    1629        8166 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_USEDHIERARCHY ) )
    1630         318 :         aRet <<= (sal_Int32) getUsedHierarchy();
    1631        7848 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIENTATION ) )
    1632             :     {
    1633        2930 :         sheet::DataPilotFieldOrientation eVal = (sheet::DataPilotFieldOrientation)getOrientation();
    1634        2930 :         aRet <<= eVal;
    1635             :     }
    1636        4918 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FUNCTION ) )
    1637             :     {
    1638         327 :         sheet::GeneralFunction eVal = (sheet::GeneralFunction)getFunction();
    1639         327 :         aRet <<= eVal;
    1640             :     }
    1641        4591 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_REFVALUE ) )
    1642           0 :         aRet <<= aReferenceValue;
    1643        4591 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ISDATALAYOUT ) )                 // read-only properties
    1644        2726 :         lcl_SetBoolInAny( aRet, getIsDataLayoutDimension() );
    1645        1865 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_NUMBERFO ) )
    1646             :     {
    1647         554 :         sal_Int32 nFormat = 0;
    1648         554 :         sheet::GeneralFunction eFunc = (sheet::GeneralFunction)getFunction();
    1649             :         // #i63745# don't use source format for "count"
    1650         554 :         if ( eFunc != sheet::GeneralFunction_COUNT && eFunc != sheet::GeneralFunction_COUNTNUMS )
    1651         550 :             nFormat = pSource->GetData()->GetNumberFormat( ( nSourceDim >= 0 ) ? nSourceDim : nDim );
    1652             : 
    1653         554 :         switch ( aReferenceValue.ReferenceType )
    1654             :         {
    1655             :         case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE:
    1656             :         case sheet::DataPilotFieldReferenceType::ITEM_PERCENTAGE_DIFFERENCE:
    1657             :         case sheet::DataPilotFieldReferenceType::ROW_PERCENTAGE:
    1658             :         case sheet::DataPilotFieldReferenceType::COLUMN_PERCENTAGE:
    1659             :         case sheet::DataPilotFieldReferenceType::TOTAL_PERCENTAGE:
    1660           6 :             nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_PERCENT_DEC2 );
    1661           6 :             break;
    1662             :         case sheet::DataPilotFieldReferenceType::INDEX:
    1663           0 :             nFormat = pSource->GetData()->GetNumberFormatByIdx( (NfIndexTableOffset)NF_NUMBER_SYSTEM );
    1664           0 :             break;
    1665             :         default:
    1666         548 :             break;
    1667             :         }
    1668             : 
    1669         554 :         aRet <<= nFormat;
    1670             :     }
    1671        1311 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_ORIGINAL ) )
    1672             :     {
    1673         508 :         uno::Reference<container::XNamed> xOriginal;
    1674         508 :         if (nSourceDim >= 0)
    1675           0 :             xOriginal = pSource->GetDimensionsObject()->getByIndex(nSourceDim);
    1676         508 :         aRet <<= xOriginal;
    1677             :     }
    1678         803 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_ORIGINAL_POS))
    1679             :     {
    1680           4 :         sal_Int32 nPos = static_cast<sal_Int32>(nSourceDim);
    1681           4 :         aRet <<= nPos;
    1682             :     }
    1683         799 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_FILTER ) )
    1684             :     {
    1685           0 :         if ( bHasSelectedPage )
    1686             :         {
    1687             :             // single filter field: first field equal to selected string
    1688             :             sheet::TableFilterField aField( sheet::FilterConnection_AND, 0,
    1689           0 :                     sheet::FilterOperator_EQUAL, false, 0.0, aSelectedPage );
    1690           0 :             aRet <<= uno::Sequence<sheet::TableFilterField>( &aField, 1 );
    1691             :         }
    1692             :         else
    1693           0 :             aRet <<= uno::Sequence<sheet::TableFilterField>(0);
    1694             :     }
    1695         799 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    1696         392 :         aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString("");
    1697         407 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FIELD_SUBTOTALNAME))
    1698           4 :         aRet <<= mpSubtotalName.get() ? *mpSubtotalName : OUString("");
    1699         403 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_HAS_HIDDEN_MEMBER))
    1700         400 :         aRet <<= static_cast<sal_Bool>(mbHasHiddenMember);
    1701           3 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_FLAGS))
    1702             :     {
    1703           3 :         sal_Int32 nFlags = 0;       // tabular data: all orientations are possible
    1704           3 :         aRet <<= nFlags;
    1705             :     }
    1706             :     else
    1707             :     {
    1708             :         OSL_FAIL("unknown property");
    1709             :         //! THROW( UnknownPropertyException() );
    1710             :     }
    1711        8566 :     return aRet;
    1712             : }
    1713             : 
    1714           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPDimension )
    1715             : 
    1716             : // -----------------------------------------------------------------------
    1717             : 
    1718         279 : ScDPHierarchies::ScDPHierarchies( ScDPSource* pSrc, long nD ) :
    1719             :     pSource( pSrc ),
    1720             :     nDim( nD ),
    1721         279 :     ppHiers( NULL )
    1722             : {
    1723             :     //! hold pSource
    1724             : 
    1725             :     //  date columns have 3 hierarchies (flat/quarter/week), other columns only one
    1726             : 
    1727             :     // #i52547# don't offer the incomplete date hierarchy implementation
    1728         279 :     nHierCount = 1;
    1729         279 : }
    1730             : 
    1731         837 : ScDPHierarchies::~ScDPHierarchies()
    1732             : {
    1733             :     //! release pSource
    1734             : 
    1735         279 :     if (ppHiers)
    1736             :     {
    1737         558 :         for (long i=0; i<nHierCount; i++)
    1738         279 :             if ( ppHiers[i] )
    1739         279 :                 ppHiers[i]->release();      // ref-counted
    1740         279 :         delete[] ppHiers;
    1741             :     }
    1742         558 : }
    1743             : 
    1744             : // very simple XNameAccess implementation using getCount/getByIndex
    1745             : 
    1746         593 : uno::Any SAL_CALL ScDPHierarchies::getByName( const OUString& aName )
    1747             :             throw(container::NoSuchElementException,
    1748             :                     lang::WrappedTargetException, uno::RuntimeException)
    1749             : {
    1750         593 :     long nCount = getCount();
    1751         593 :     for (long i=0; i<nCount; i++)
    1752         593 :         if ( getByIndex(i)->getName() == aName )
    1753             :         {
    1754         593 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1755        1186 :             uno::Any aRet;
    1756         593 :             aRet <<= xNamed;
    1757        1779 :             return aRet;
    1758             :         }
    1759             : 
    1760           0 :     throw container::NoSuchElementException();
    1761             : }
    1762             : 
    1763         596 : uno::Sequence<OUString> SAL_CALL ScDPHierarchies::getElementNames() throw(uno::RuntimeException)
    1764             : {
    1765         596 :     long nCount = getCount();
    1766         596 :     uno::Sequence<OUString> aSeq(nCount);
    1767         596 :     OUString* pArr = aSeq.getArray();
    1768        1192 :     for (long i=0; i<nCount; i++)
    1769         596 :         pArr[i] = getByIndex(i)->getName();
    1770         596 :     return aSeq;
    1771             : }
    1772             : 
    1773           0 : sal_Bool SAL_CALL ScDPHierarchies::hasByName( const OUString& aName ) throw(uno::RuntimeException)
    1774             : {
    1775           0 :     long nCount = getCount();
    1776           0 :     for (long i=0; i<nCount; i++)
    1777           0 :         if ( getByIndex(i)->getName() == aName )
    1778           0 :             return sal_True;
    1779           0 :     return false;
    1780             : }
    1781             : 
    1782           0 : uno::Type SAL_CALL ScDPHierarchies::getElementType() throw(uno::RuntimeException)
    1783             : {
    1784           0 :     return getCppuType((uno::Reference<container::XNamed>*)0);
    1785             : }
    1786             : 
    1787           0 : sal_Bool SAL_CALL ScDPHierarchies::hasElements() throw(uno::RuntimeException)
    1788             : {
    1789           0 :     return ( getCount() > 0 );
    1790             : }
    1791             : 
    1792             : // end of XNameAccess implementation
    1793             : 
    1794        1524 : long ScDPHierarchies::getCount() const
    1795             : {
    1796        1524 :     return nHierCount;
    1797             : }
    1798             : 
    1799        3210 : ScDPHierarchy* ScDPHierarchies::getByIndex(long nIndex) const
    1800             : {
    1801             :     //  pass hierarchy index to new object in case the implementation
    1802             :     //  will be extended to more than one hierarchy
    1803             : 
    1804        3210 :     if ( nIndex >= 0 && nIndex < nHierCount )
    1805             :     {
    1806        3210 :         if ( !ppHiers )
    1807             :         {
    1808         279 :             ((ScDPHierarchies*)this)->ppHiers = new ScDPHierarchy*[nHierCount];
    1809         558 :             for (long i=0; i<nHierCount; i++)
    1810         279 :                 ppHiers[i] = NULL;
    1811             :         }
    1812        3210 :         if ( !ppHiers[nIndex] )
    1813             :         {
    1814         279 :             ppHiers[nIndex] = new ScDPHierarchy( pSource, nDim, nIndex );
    1815         279 :             ppHiers[nIndex]->acquire();         // ref-counted
    1816             :         }
    1817             : 
    1818        3210 :         return ppHiers[nIndex];
    1819             :     }
    1820             : 
    1821           0 :     return NULL;    //! exception?
    1822             : }
    1823             : 
    1824             : // -----------------------------------------------------------------------
    1825             : 
    1826         279 : ScDPHierarchy::ScDPHierarchy( ScDPSource* pSrc, long nD, long nH ) :
    1827             :     pSource( pSrc ),
    1828             :     nDim( nD ),
    1829             :     nHier( nH ),
    1830         279 :     pLevels( NULL )
    1831             : {
    1832             :     //! hold pSource
    1833         279 : }
    1834             : 
    1835         837 : ScDPHierarchy::~ScDPHierarchy()
    1836             : {
    1837             :     //! release pSource
    1838             : 
    1839         279 :     if (pLevels)
    1840         279 :         pLevels->release();     // ref-counted
    1841         558 : }
    1842             : 
    1843        2021 : ScDPLevels* ScDPHierarchy::GetLevelsObject()
    1844             : {
    1845        2021 :     if (!pLevels)
    1846             :     {
    1847         279 :         pLevels = new ScDPLevels( pSource, nDim, nHier );
    1848         279 :         pLevels->acquire();     // ref-counted
    1849             :     }
    1850        2021 :     return pLevels;
    1851             : }
    1852             : 
    1853         593 : uno::Reference<container::XNameAccess> SAL_CALL ScDPHierarchy::getLevels()
    1854             :                                                     throw(uno::RuntimeException)
    1855             : {
    1856         593 :     return GetLevelsObject();
    1857             : }
    1858             : 
    1859        1189 : OUString SAL_CALL ScDPHierarchy::getName() throw(uno::RuntimeException)
    1860             : {
    1861        1189 :     OUString aRet;        //! globstr-ID !!!!
    1862        1189 :     switch (nHier)
    1863             :     {
    1864             :         case SC_DAPI_HIERARCHY_FLAT:
    1865        1189 :             aRet = OUString("flat");
    1866        1189 :             break;  //! name ???????
    1867             :         case SC_DAPI_HIERARCHY_QUARTER:
    1868           0 :             aRet = OUString("Quarter");
    1869           0 :             break;  //! name ???????
    1870             :         case SC_DAPI_HIERARCHY_WEEK:
    1871           0 :             aRet = OUString("Week");
    1872           0 :             break;  //! name ???????
    1873             :         default:
    1874             :             OSL_FAIL( "ScDPHierarchy::getName: unexpected hierarchy" );
    1875           0 :             break;
    1876             :     }
    1877        1189 :     return aRet;
    1878             : }
    1879             : 
    1880           0 : void SAL_CALL ScDPHierarchy::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException)
    1881             : {
    1882             :     OSL_FAIL("not implemented");        //! exception?
    1883           0 : }
    1884             : 
    1885             : // -----------------------------------------------------------------------
    1886             : 
    1887         279 : ScDPLevels::ScDPLevels( ScDPSource* pSrc, long nD, long nH ) :
    1888             :     pSource( pSrc ),
    1889             :     nDim( nD ),
    1890             :     nHier( nH ),
    1891         279 :     ppLevs( NULL )
    1892             : {
    1893             :     //! hold pSource
    1894             : 
    1895             :     //  text columns have only one level
    1896             : 
    1897         279 :     long nSrcDim = pSource->GetSourceDim( nDim );
    1898         279 :     if ( pSource->IsDateDimension( nSrcDim ) )
    1899             :     {
    1900           8 :         switch ( nHier )
    1901             :         {
    1902           8 :             case SC_DAPI_HIERARCHY_FLAT:    nLevCount = SC_DAPI_FLAT_LEVELS;    break;
    1903           0 :             case SC_DAPI_HIERARCHY_QUARTER: nLevCount = SC_DAPI_QUARTER_LEVELS; break;
    1904           0 :             case SC_DAPI_HIERARCHY_WEEK:    nLevCount = SC_DAPI_WEEK_LEVELS;    break;
    1905             :             default:
    1906             :                 OSL_FAIL("wrong hierarchy");
    1907           0 :                 nLevCount = 0;
    1908             :         }
    1909             :     }
    1910             :     else
    1911         271 :         nLevCount = 1;
    1912         279 : }
    1913             : 
    1914         837 : ScDPLevels::~ScDPLevels()
    1915             : {
    1916             :     //! release pSource
    1917             : 
    1918         279 :     if (ppLevs)
    1919             :     {
    1920         558 :         for (long i=0; i<nLevCount; i++)
    1921         279 :             if ( ppLevs[i] )
    1922         279 :                 ppLevs[i]->release();   // ref-counted
    1923         279 :         delete[] ppLevs;
    1924             :     }
    1925         558 : }
    1926             : 
    1927             : // very simple XNameAccess implementation using getCount/getByIndex
    1928             : 
    1929         593 : uno::Any SAL_CALL ScDPLevels::getByName( const OUString& aName )
    1930             :             throw(container::NoSuchElementException,
    1931             :                     lang::WrappedTargetException, uno::RuntimeException)
    1932             : {
    1933         593 :     long nCount = getCount();
    1934         593 :     for (long i=0; i<nCount; i++)
    1935         593 :         if ( getByIndex(i)->getName() == aName )
    1936             :         {
    1937         593 :             uno::Reference<container::XNamed> xNamed = getByIndex(i);
    1938        1186 :             uno::Any aRet;
    1939         593 :             aRet <<= xNamed;
    1940        1779 :             return aRet;
    1941             :         }
    1942             : 
    1943           0 :     throw container::NoSuchElementException();
    1944             : }
    1945             : 
    1946         593 : uno::Sequence<OUString> SAL_CALL ScDPLevels::getElementNames() throw(uno::RuntimeException)
    1947             : {
    1948         593 :     long nCount = getCount();
    1949         593 :     uno::Sequence<OUString> aSeq(nCount);
    1950         593 :     OUString* pArr = aSeq.getArray();
    1951        1186 :     for (long i=0; i<nCount; i++)
    1952         593 :         pArr[i] = getByIndex(i)->getName();
    1953         593 :     return aSeq;
    1954             : }
    1955             : 
    1956           0 : sal_Bool SAL_CALL ScDPLevels::hasByName( const OUString& aName ) throw(uno::RuntimeException)
    1957             : {
    1958           0 :     long nCount = getCount();
    1959           0 :     for (long i=0; i<nCount; i++)
    1960           0 :         if ( getByIndex(i)->getName() == aName )
    1961           0 :             return sal_True;
    1962           0 :     return false;
    1963             : }
    1964             : 
    1965           0 : uno::Type SAL_CALL ScDPLevels::getElementType() throw(uno::RuntimeException)
    1966             : {
    1967           0 :     return getCppuType((uno::Reference<container::XNamed>*)0);
    1968             : }
    1969             : 
    1970           0 : sal_Bool SAL_CALL ScDPLevels::hasElements() throw(uno::RuntimeException)
    1971             : {
    1972           0 :     return ( getCount() > 0 );
    1973             : }
    1974             : 
    1975             : // end of XNameAccess implementation
    1976             : 
    1977        1521 : long ScDPLevels::getCount() const
    1978             : {
    1979        1521 :     return nLevCount;
    1980             : }
    1981             : 
    1982        3172 : ScDPLevel* ScDPLevels::getByIndex(long nIndex) const
    1983             : {
    1984        3172 :     if ( nIndex >= 0 && nIndex < nLevCount )
    1985             :     {
    1986        3172 :         if ( !ppLevs )
    1987             :         {
    1988         279 :             ((ScDPLevels*)this)->ppLevs = new ScDPLevel*[nLevCount];
    1989         558 :             for (long i=0; i<nLevCount; i++)
    1990         279 :                 ppLevs[i] = NULL;
    1991             :         }
    1992        3172 :         if ( !ppLevs[nIndex] )
    1993             :         {
    1994         279 :             ppLevs[nIndex] = new ScDPLevel( pSource, nDim, nHier, nIndex );
    1995         279 :             ppLevs[nIndex]->acquire();      // ref-counted
    1996             :         }
    1997             : 
    1998        3172 :         return ppLevs[nIndex];
    1999             :     }
    2000             : 
    2001           0 :     return NULL;    //! exception?
    2002             : }
    2003             : 
    2004             : // -----------------------------------------------------------------------
    2005             : 
    2006             : class ScDPGlobalMembersOrder
    2007             : {
    2008             :     ScDPLevel&  rLevel;
    2009             :     sal_Bool        bAscending;
    2010             : 
    2011             : public:
    2012         202 :             ScDPGlobalMembersOrder( ScDPLevel& rLev, sal_Bool bAsc ) :
    2013             :                 rLevel(rLev),
    2014         202 :                 bAscending(bAsc)
    2015         202 :             {}
    2016        1750 :             ~ScDPGlobalMembersOrder() {}
    2017             : 
    2018             :     sal_Bool operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const;
    2019             : };
    2020             : 
    2021        1493 : sal_Bool ScDPGlobalMembersOrder::operator()( sal_Int32 nIndex1, sal_Int32 nIndex2 ) const
    2022             : {
    2023        1493 :     sal_Int32 nCompare = 0;
    2024             :     // seems that some ::std::sort() implementations pass the same index twice
    2025        1493 :     if( nIndex1 != nIndex2 )
    2026             :     {
    2027        1493 :         ScDPMembers* pMembers = rLevel.GetMembersObject();
    2028        1493 :         ScDPMember* pMember1 = pMembers->getByIndex(nIndex1);
    2029        1493 :         ScDPMember* pMember2 = pMembers->getByIndex(nIndex2);
    2030        1493 :         nCompare = pMember1->Compare( *pMember2 );
    2031             :     }
    2032        1493 :     return bAscending ? (nCompare < 0) : (nCompare > 0);
    2033             : }
    2034             : 
    2035             : // -----------------------------------------------------------------------
    2036             : 
    2037         279 : ScDPLevel::ScDPLevel( ScDPSource* pSrc, long nD, long nH, long nL ) :
    2038             :     pSource( pSrc ),
    2039             :     nDim( nD ),
    2040             :     nHier( nH ),
    2041             :     nLev( nL ),
    2042             :     pMembers( NULL ),
    2043         279 :     aSortInfo( EMPTY_STRING, sal_True, sheet::DataPilotFieldSortMode::NAME ),   // default: sort by name
    2044             :     nSortMeasure( 0 ),
    2045             :     nAutoMeasure( 0 ),
    2046             :     bShowEmpty( false ),
    2047         558 :     bEnableLayout( false )
    2048             : {
    2049             :     //! hold pSource
    2050             :     //  aSubTotals is empty
    2051         279 : }
    2052             : 
    2053         837 : ScDPLevel::~ScDPLevel()
    2054             : {
    2055             :     //! release pSource
    2056             : 
    2057         279 :     if ( pMembers )
    2058         173 :         pMembers->release();    // ref-counted
    2059         558 : }
    2060             : 
    2061         202 : void ScDPLevel::EvaluateSortOrder()
    2062             : {
    2063         202 :     switch (aSortInfo.Mode)
    2064             :     {
    2065             :         case sheet::DataPilotFieldSortMode::DATA:
    2066             :             {
    2067             :                 // find index of measure (index among data dimensions)
    2068             : 
    2069           0 :                 long nMeasureCount = pSource->GetDataDimensionCount();
    2070           0 :                 for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
    2071             :                 {
    2072           0 :                     if (pSource->GetDataDimName(nMeasure).equals(aSortInfo.Field))
    2073             :                     {
    2074           0 :                         nSortMeasure = nMeasure;
    2075           0 :                         break;
    2076             :                     }
    2077             :                 }
    2078             : 
    2079             :                 //! error if not found?
    2080             :             }
    2081           0 :             break;
    2082             :         case sheet::DataPilotFieldSortMode::MANUAL:
    2083             :         case sheet::DataPilotFieldSortMode::NAME:
    2084             :             {
    2085         202 :                 ScDPMembers* pLocalMembers = GetMembersObject();
    2086         202 :                 long nCount = pLocalMembers->getCount();
    2087             : 
    2088         202 :                 aGlobalOrder.resize( nCount );
    2089        1153 :                 for (long nPos=0; nPos<nCount; nPos++)
    2090         951 :                     aGlobalOrder[nPos] = nPos;
    2091             : 
    2092             :                 // allow manual or name (manual is always ascending)
    2093         202 :                 sal_Bool bAscending = ( aSortInfo.Mode == sheet::DataPilotFieldSortMode::MANUAL || aSortInfo.IsAscending );
    2094         202 :                 ScDPGlobalMembersOrder aComp( *this, bAscending );
    2095         202 :                 ::std::sort( aGlobalOrder.begin(), aGlobalOrder.end(), aComp );
    2096             :             }
    2097         202 :             break;
    2098             :     }
    2099             : 
    2100         202 :     if ( aAutoShowInfo.IsEnabled )
    2101             :     {
    2102             :         // find index of measure (index among data dimensions)
    2103             : 
    2104           1 :         long nMeasureCount = pSource->GetDataDimensionCount();
    2105           2 :         for (long nMeasure=0; nMeasure<nMeasureCount; nMeasure++)
    2106             :         {
    2107           1 :             if (pSource->GetDataDimName(nMeasure).equals(aAutoShowInfo.DataField))
    2108             :             {
    2109           0 :                 nAutoMeasure = nMeasure;
    2110           0 :                 break;
    2111             :             }
    2112             :         }
    2113             : 
    2114             :         //! error if not found?
    2115             :     }
    2116         202 : }
    2117             : 
    2118         186 : void ScDPLevel::SetEnableLayout(bool bSet)
    2119             : {
    2120         186 :     bEnableLayout = bSet;
    2121         186 : }
    2122             : 
    2123        3362 : ScDPMembers* ScDPLevel::GetMembersObject()
    2124             : {
    2125        3362 :     if (!pMembers)
    2126             :     {
    2127         173 :         pMembers = new ScDPMembers( pSource, nDim, nHier, nLev );
    2128         173 :         pMembers->acquire();    // ref-counted
    2129             :     }
    2130        3362 :     return pMembers;
    2131             : }
    2132             : 
    2133         140 : uno::Reference<container::XNameAccess> SAL_CALL ScDPLevel::getMembers() throw(uno::RuntimeException)
    2134             : {
    2135         140 :     return GetMembersObject();
    2136             : }
    2137             : 
    2138         198 : uno::Sequence<sheet::MemberResult> SAL_CALL ScDPLevel::getResults() throw(uno::RuntimeException)
    2139             : {
    2140         198 :     const uno::Sequence<sheet::MemberResult>* pRes = pSource->GetMemberResults( this );
    2141         198 :     if (pRes)
    2142         198 :         return *pRes;
    2143             : 
    2144           0 :     return uno::Sequence<sheet::MemberResult>(0);       //! Error?
    2145             : }
    2146             : 
    2147        1438 : OUString SAL_CALL ScDPLevel::getName() throw(uno::RuntimeException)
    2148             : {
    2149        1438 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2150        1438 :     if ( pSource->IsDateDimension( nSrcDim ) )
    2151             :     {
    2152          40 :         OUString aRet;        //! globstr-ID !!!!
    2153             : 
    2154          40 :         if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
    2155             :         {
    2156           0 :             switch ( nLev )
    2157             :             {
    2158             :                 case SC_DAPI_LEVEL_YEAR:
    2159           0 :                     aRet = OUString("Year");
    2160           0 :                     break;
    2161             :                 case SC_DAPI_LEVEL_QUARTER:
    2162           0 :                     aRet = OUString("Quarter");
    2163           0 :                     break;
    2164             :                 case SC_DAPI_LEVEL_MONTH:
    2165           0 :                     aRet = OUString("Month");
    2166           0 :                     break;
    2167             :                 case SC_DAPI_LEVEL_DAY:
    2168           0 :                     aRet = OUString("Day");
    2169           0 :                     break;
    2170             :                 default:
    2171             :                     OSL_FAIL( "ScDPLevel::getName: unexpected level" );
    2172           0 :                     break;
    2173             :             }
    2174             :         }
    2175          40 :         else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
    2176             :         {
    2177           0 :             switch ( nLev )
    2178             :             {
    2179             :                 case SC_DAPI_LEVEL_YEAR:
    2180           0 :                     aRet = OUString("Year");
    2181           0 :                     break;
    2182             :                 case SC_DAPI_LEVEL_WEEK:
    2183           0 :                     aRet = OUString("Week");
    2184           0 :                     break;
    2185             :                 case SC_DAPI_LEVEL_WEEKDAY:
    2186           0 :                     aRet = OUString("Weekday");
    2187           0 :                     break;
    2188             :                 default:
    2189             :                     OSL_FAIL( "ScDPLevel::getName: unexpected level" );
    2190           0 :                     break;
    2191             :             }
    2192             :         }
    2193          40 :         if (!aRet.isEmpty())
    2194           0 :             return aRet;
    2195             :     }
    2196             : 
    2197        1438 :     ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
    2198        1438 :     if (!pDim)
    2199           0 :         return OUString();
    2200             : 
    2201        1438 :     return pDim->getName();
    2202             : }
    2203             : 
    2204           0 : void SAL_CALL ScDPLevel::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException)
    2205             : {
    2206             :     OSL_FAIL("not implemented");        //! exception?
    2207           0 : }
    2208             : 
    2209        6819 : uno::Sequence<sheet::GeneralFunction> ScDPLevel::getSubTotals() const
    2210             : {
    2211             :     //! separate functions for settings and evaluation?
    2212             : 
    2213        6819 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2214        6819 :     if ( !pSource->SubTotalAllowed( nSrcDim ) )
    2215        5546 :         return uno::Sequence<sheet::GeneralFunction>(0);
    2216             : 
    2217        1273 :     return aSubTotals;
    2218             : }
    2219             : 
    2220         762 : bool ScDPLevel::getShowEmpty() const
    2221             : {
    2222         762 :     return bShowEmpty;
    2223             : }
    2224             : 
    2225             : // XPropertySet
    2226             : 
    2227           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPLevel::getPropertySetInfo()
    2228             :                                                         throw(uno::RuntimeException)
    2229             : {
    2230           0 :     SolarMutexGuard aGuard;
    2231             : 
    2232             :     static SfxItemPropertyMapEntry aDPLevelMap_Impl[] =
    2233             :     {
    2234             :         //! change type of AutoShow/Layout/Sorting to API struct when available
    2235           0 :         {MAP_CHAR_LEN(SC_UNO_DP_AUTOSHOW), 0,  &getCppuType((sheet::DataPilotFieldAutoShowInfo*)0),     0, 0 },
    2236           0 :         {MAP_CHAR_LEN(SC_UNO_DP_LAYOUT),   0,  &getCppuType((sheet::DataPilotFieldLayoutInfo*)0),       0, 0 },
    2237           0 :         {MAP_CHAR_LEN(SC_UNO_DP_SHOWEMPTY), 0,  &getBooleanCppuType(),                                   0, 0 },
    2238           0 :         {MAP_CHAR_LEN(SC_UNO_DP_SORTING),  0,  &getCppuType((sheet::DataPilotFieldSortInfo*)0),         0, 0 },
    2239           0 :         {MAP_CHAR_LEN(SC_UNO_DP_SUBTOTAL), 0,  &getCppuType((uno::Sequence<sheet::GeneralFunction>*)0), 0, 0 },
    2240             :         {0,0,0,0,0,0}
    2241           0 :     };
    2242             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    2243           0 :         new SfxItemPropertySetInfo( aDPLevelMap_Impl );
    2244           0 :     return aRef;
    2245             : }
    2246             : 
    2247         363 : void SAL_CALL ScDPLevel::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    2248             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    2249             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    2250             :                         uno::RuntimeException)
    2251             : {
    2252         363 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
    2253          82 :         bShowEmpty = lcl_GetBoolFromAny(aValue);
    2254         281 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
    2255          41 :         aValue >>= aSubTotals;
    2256         240 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
    2257          78 :         aValue >>= aSortInfo;
    2258         162 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
    2259          82 :         aValue >>= aAutoShowInfo;
    2260          80 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
    2261          80 :         aValue >>= aLayoutInfo;
    2262             :     else
    2263             :     {
    2264             :         OSL_FAIL("unknown property");
    2265             :     }
    2266         363 : }
    2267             : 
    2268         264 : uno::Any SAL_CALL ScDPLevel::getPropertyValue( const OUString& aPropertyName )
    2269             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    2270             :                         uno::RuntimeException)
    2271             : {
    2272         264 :     uno::Any aRet;
    2273         264 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWEMPTY ) )
    2274           3 :         lcl_SetBoolInAny(aRet, bShowEmpty);
    2275         261 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SUBTOTAL ) )
    2276             :     {
    2277           0 :         uno::Sequence<sheet::GeneralFunction> aSeq = getSubTotals();        //! avoid extra copy?
    2278           0 :         aRet <<= aSeq;
    2279             :     }
    2280         261 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SORTING ) )
    2281           3 :         aRet <<= aSortInfo;
    2282         258 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_AUTOSHOW ) )
    2283           3 :         aRet <<= aAutoShowInfo;
    2284         255 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_LAYOUT ) )
    2285           3 :         aRet <<= aLayoutInfo;
    2286         252 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2287             :     {
    2288             :         // read only property
    2289         252 :         long nSrcDim = pSource->GetSourceDim(nDim);
    2290         252 :         ScDPDimension* pDim = pSource->GetDimensionsObject()->getByIndex(nSrcDim);
    2291         252 :         if (!pDim)
    2292           0 :             return aRet;
    2293             : 
    2294         252 :         const OUString* pLayoutName = pDim->GetLayoutName();
    2295         252 :         if (!pLayoutName)
    2296         252 :             return aRet;
    2297             : 
    2298           0 :         aRet <<= *pLayoutName;
    2299             :     }
    2300             :     else
    2301             :     {
    2302             :         OSL_FAIL("unknown property");
    2303             :     }
    2304          12 :     return aRet;
    2305             : }
    2306             : 
    2307           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPLevel )
    2308             : 
    2309             : // -----------------------------------------------------------------------
    2310             : 
    2311         173 : ScDPMembers::ScDPMembers( ScDPSource* pSrc, long nD, long nH, long nL ) :
    2312             :     pSource( pSrc ),
    2313             :     nDim( nD ),
    2314             :     nHier( nH ),
    2315         173 :     nLev( nL )
    2316             : {
    2317             :     //! hold pSource
    2318             : 
    2319         173 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2320         173 :     if ( pSource->IsDataLayoutDimension(nSrcDim) )
    2321           6 :         nMbrCount = pSource->GetDataDimensionCount();
    2322         167 :     else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2323             :     {
    2324           0 :         nMbrCount = 0;
    2325           0 :         if ( nHier == SC_DAPI_HIERARCHY_QUARTER )
    2326             :         {
    2327           0 :             switch (nLev)
    2328             :             {
    2329             :                 case SC_DAPI_LEVEL_YEAR:
    2330             :                     {
    2331           0 :                         const ScDPItemData* pLastNumData = NULL;
    2332           0 :                         for ( SCROW n = 0 ;n <GetSrcItemsCount() ; n-- )
    2333             :                         {
    2334           0 :                             const ScDPItemData* pData  = GetSrcItemDataByIndex( n );
    2335           0 :                             if ( pData && pData->HasStringData() )
    2336           0 :                                 break;
    2337             :                             else
    2338           0 :                                 pLastNumData = pData;
    2339             :                         }
    2340             : 
    2341           0 :                         if ( pLastNumData )
    2342             :                         {
    2343           0 :                             const ScDPItemData*  pFirstData = GetSrcItemDataByIndex( 0 );
    2344           0 :                             double fFirstVal = pFirstData->GetValue();
    2345           0 :                             double fLastVal = pLastNumData->GetValue();
    2346             : 
    2347             :                             long nFirstYear = pSource->GetData()->GetDatePart(
    2348           0 :                                         (long)::rtl::math::approxFloor( fFirstVal ),
    2349           0 :                                         nHier, nLev );
    2350             :                             long nLastYear = pSource->GetData()->GetDatePart(
    2351           0 :                                         (long)::rtl::math::approxFloor( fLastVal ),
    2352           0 :                                         nHier, nLev );
    2353             : 
    2354           0 :                             nMbrCount = nLastYear + 1 - nFirstYear;
    2355             :                         }
    2356             :                         else
    2357           0 :                             nMbrCount = 0;      // no values
    2358             :                     }
    2359           0 :                     break;
    2360           0 :                 case SC_DAPI_LEVEL_QUARTER: nMbrCount = 4;  break;
    2361           0 :                 case SC_DAPI_LEVEL_MONTH:   nMbrCount = 12; break;
    2362           0 :                 case SC_DAPI_LEVEL_DAY:     nMbrCount = 31; break;
    2363             :                 default:
    2364             :                     OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
    2365           0 :                     break;
    2366             :             }
    2367             :         }
    2368           0 :         else if ( nHier == SC_DAPI_HIERARCHY_WEEK )
    2369             :         {
    2370           0 :             switch (nLev)
    2371             :             {
    2372           0 :                 case SC_DAPI_LEVEL_YEAR:    nMbrCount = 1;  break;      //! get years from source
    2373           0 :                 case SC_DAPI_LEVEL_WEEK:    nMbrCount = 53; break;
    2374           0 :                 case SC_DAPI_LEVEL_WEEKDAY: nMbrCount = 7;  break;
    2375             :                 default:
    2376             :                     OSL_FAIL( "ScDPMembers::ScDPMembers: unexpected level" );
    2377           0 :                     break;
    2378             :             }
    2379             :         }
    2380             :     }
    2381             :     else
    2382         167 :         nMbrCount = pSource->GetData()->GetMembersCount( nSrcDim );
    2383         173 : }
    2384             : 
    2385         346 : ScDPMembers::~ScDPMembers()
    2386             : {
    2387         346 : }
    2388             : 
    2389             : // XNameAccess implementation using getCount/getByIndex
    2390             : 
    2391        1198 : sal_Int32 ScDPMembers::GetIndexFromName( const OUString& rName ) const
    2392             : {
    2393        1198 :     if ( aHashMap.empty() )
    2394             :     {
    2395             :         // store the index for each name
    2396             : 
    2397          80 :         sal_Int32 nCount = getCount();
    2398         431 :         for (sal_Int32 i=0; i<nCount; i++)
    2399         351 :             aHashMap[ getByIndex(i)->getName() ] = i;
    2400             :     }
    2401             : 
    2402        1198 :     ScDPMembersHashMap::const_iterator aIter = aHashMap.find( rName );
    2403        1198 :     if ( aIter != aHashMap.end() )
    2404        1188 :         return aIter->second;           // found index
    2405             :     else
    2406          10 :         return -1;                      // not found
    2407             : }
    2408             : 
    2409         484 : uno::Any SAL_CALL ScDPMembers::getByName( const OUString& aName )
    2410             :             throw(container::NoSuchElementException,
    2411             :                     lang::WrappedTargetException, uno::RuntimeException)
    2412             : {
    2413         484 :     sal_Int32 nIndex = GetIndexFromName( aName );
    2414         484 :     if ( nIndex >= 0 )
    2415             :     {
    2416         484 :         uno::Reference<container::XNamed> xNamed = getByIndex(nIndex);
    2417         968 :         uno::Any aRet;
    2418         484 :         aRet <<= xNamed;
    2419        1452 :         return aRet;
    2420             :     }
    2421             : 
    2422           0 :     throw container::NoSuchElementException();
    2423             : }
    2424             : 
    2425          80 : uno::Sequence<OUString> SAL_CALL ScDPMembers::getElementNames() throw(uno::RuntimeException)
    2426             : {
    2427             :     // Return list of names in sorted order,
    2428             :     // so it's displayed in that order in the field options dialog.
    2429             :     // Sorting is done at the level object (parent of this).
    2430             : 
    2431          80 :     ScDPLevel* pLevel = pSource->GetDimensionsObject()->getByIndex(nDim)->
    2432          80 :         GetHierarchiesObject()->getByIndex(nHier)->GetLevelsObject()->getByIndex(nLev);
    2433          80 :     pLevel->EvaluateSortOrder();
    2434          80 :     const std::vector<sal_Int32>& rGlobalOrder = pLevel->GetGlobalOrder();
    2435          80 :     bool bSort = !rGlobalOrder.empty();
    2436             : 
    2437          80 :     long nCount = getCount();
    2438          80 :     uno::Sequence<OUString> aSeq(nCount);
    2439          80 :     OUString* pArr = aSeq.getArray();
    2440         474 :     for (long i=0; i<nCount; i++)
    2441         394 :         pArr[i] = getByIndex(bSort ? rGlobalOrder[i] : i)->getName();
    2442          80 :     return aSeq;
    2443             : }
    2444             : 
    2445         254 : sal_Bool SAL_CALL ScDPMembers::hasByName( const OUString& aName ) throw(uno::RuntimeException)
    2446             : {
    2447         254 :     return ( GetIndexFromName( aName ) >= 0 );
    2448             : }
    2449             : 
    2450           0 : uno::Type SAL_CALL ScDPMembers::getElementType() throw(uno::RuntimeException)
    2451             : {
    2452           0 :     return getCppuType((uno::Reference<container::XNamed>*)0);
    2453             : }
    2454             : 
    2455           0 : sal_Bool SAL_CALL ScDPMembers::hasElements() throw(uno::RuntimeException)
    2456             : {
    2457           0 :     return ( getCount() > 0 );
    2458             : }
    2459             : 
    2460             : // end of XNameAccess implementation
    2461             : 
    2462        1186 : long ScDPMembers::getCount() const
    2463             : {
    2464        1186 :     return nMbrCount;
    2465             : }
    2466             : 
    2467         100 : long ScDPMembers::getMinMembers() const
    2468             : {
    2469             :     // used in lcl_CountMinMembers
    2470             : 
    2471         100 :     long nVisCount = 0;
    2472         100 :     if (!maMembers.empty())
    2473             :     {
    2474          98 :         MembersType::const_iterator it = maMembers.begin(), itEnd = maMembers.end();
    2475         573 :         for (; it != itEnd; ++it)
    2476             :         {
    2477             :             //  count only visible with details (default is true for both)
    2478         475 :             const rtl::Reference<ScDPMember>& pMbr = *it;
    2479         475 :             if (!pMbr.get() || (pMbr->isVisible() && pMbr->getShowDetails()))
    2480         475 :                 ++nVisCount;
    2481             :         }
    2482             :     }
    2483             :     else
    2484           2 :         nVisCount = nMbrCount;      // default for all
    2485             : 
    2486         100 :     return nVisCount;
    2487             : }
    2488             : 
    2489        5958 : ScDPMember* ScDPMembers::getByIndex(long nIndex) const
    2490             : {
    2491             :     //  result of GetColumnEntries must not change between ScDPMembers ctor
    2492             :     //  and all calls to getByIndex
    2493             : 
    2494        5958 :     if ( nIndex >= 0 && nIndex < nMbrCount )
    2495             :     {
    2496        5958 :         if (maMembers.empty())
    2497         173 :             maMembers.resize(nMbrCount);
    2498             : 
    2499        5958 :         if (!maMembers[nIndex].get())
    2500             :         {
    2501         770 :             rtl::Reference<ScDPMember> pNew;
    2502         770 :             long nSrcDim = pSource->GetSourceDim( nDim );
    2503         770 :             if ( pSource->IsDataLayoutDimension(nSrcDim) )
    2504             :             {
    2505             :                 // empty name (never shown, not used for lookup)
    2506          12 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, 0));
    2507             :             }
    2508         758 :             else if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2509             :             {
    2510           0 :                 sal_Int32 nGroupBy = 0;
    2511           0 :                 sal_Int32 nVal = 0;
    2512           0 :                 OUString aName;
    2513             : 
    2514           0 :                 if ( nLev == SC_DAPI_LEVEL_YEAR )   // YEAR is in both hierarchies
    2515             :                 {
    2516             :                     //! cache year range here!
    2517             : 
    2518           0 :                     double fFirstVal = pSource->GetData()->GetMemberByIndex( nSrcDim, 0 )->GetValue();
    2519             :                     long nFirstYear = pSource->GetData()->GetDatePart(
    2520           0 :                                         (long)::rtl::math::approxFloor( fFirstVal ),
    2521           0 :                                         nHier, nLev );
    2522             : 
    2523           0 :                     nVal = nFirstYear + nIndex;
    2524             :                 }
    2525           0 :                 else if ( nHier == SC_DAPI_HIERARCHY_WEEK && nLev == SC_DAPI_LEVEL_WEEKDAY )
    2526             :                 {
    2527           0 :                     nVal = nIndex;              // DayOfWeek is 0-based
    2528           0 :                     aName = ScGlobal::GetCalendar()->getDisplayName(
    2529             :                         ::com::sun::star::i18n::CalendarDisplayIndex::DAY,
    2530           0 :                         sal::static_int_cast<sal_Int16>(nVal), 0 );
    2531             :                 }
    2532           0 :                 else if ( nHier == SC_DAPI_HIERARCHY_QUARTER && nLev == SC_DAPI_LEVEL_MONTH )
    2533             :                 {
    2534           0 :                     nVal = nIndex;              // Month is 0-based
    2535           0 :                     aName = ScGlobal::GetCalendar()->getDisplayName(
    2536             :                         ::com::sun::star::i18n::CalendarDisplayIndex::MONTH,
    2537           0 :                         sal::static_int_cast<sal_Int16>(nVal), 0 );
    2538             :                 }
    2539             :                 else
    2540           0 :                     nVal = nIndex + 1;          // Quarter, Day, Week are 1-based
    2541             : 
    2542           0 :                 switch (nLev)
    2543             :                 {
    2544             :                     case SC_DAPI_LEVEL_YEAR:
    2545           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::YEARS;
    2546           0 :                     break;
    2547             :                     case SC_DAPI_LEVEL_QUARTER:
    2548             :                     case SC_DAPI_LEVEL_WEEK:
    2549           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::QUARTERS;
    2550           0 :                     break;
    2551             :                     case SC_DAPI_LEVEL_MONTH:
    2552             :                     case SC_DAPI_LEVEL_WEEKDAY:
    2553           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::MONTHS;
    2554           0 :                     break;
    2555             :                     case SC_DAPI_LEVEL_DAY:
    2556           0 :                         nGroupBy = sheet::DataPilotFieldGroupBy::DAYS;
    2557           0 :                     break;
    2558             :                     default:
    2559             :                         ;
    2560             :                 }
    2561           0 :                 if (aName.isEmpty())
    2562           0 :                     aName = OUString::valueOf(nVal);
    2563             : 
    2564           0 :                 ScDPItemData aData(nGroupBy, nVal);
    2565           0 :                 SCROW nId = pSource->GetCache()->GetIdByItemData(nDim, aData);
    2566           0 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, nId));
    2567             :             }
    2568             :             else
    2569             :             {
    2570         758 :                 const std::vector<SCROW>& memberIndexs = pSource->GetData()->GetColumnEntries(nSrcDim);
    2571         758 :                 pNew.set(new ScDPMember(pSource, nDim, nHier, nLev, memberIndexs[nIndex]));
    2572             :             }
    2573         770 :             maMembers[nIndex] = pNew;
    2574             :         }
    2575             : 
    2576        5958 :         return maMembers[nIndex].get();
    2577             :     }
    2578             : 
    2579           0 :     return NULL;    //! exception?
    2580             : }
    2581             : 
    2582             : // -----------------------------------------------------------------------
    2583             : 
    2584         770 : ScDPMember::ScDPMember(
    2585             :     ScDPSource* pSrc, long nD, long nH, long nL, SCROW nIndex) :
    2586             :     pSource( pSrc ),
    2587             :     nDim( nD ),
    2588             :     nHier( nH ),
    2589             :     nLev( nL ),
    2590             :     mnDataId( nIndex ),
    2591             :     mpLayoutName(NULL),
    2592             :     nPosition( -1 ),
    2593             :     bVisible( true ),
    2594         770 :     bShowDet( true )
    2595             : {
    2596             :     //! hold pSource
    2597         770 : }
    2598             : 
    2599        1540 : ScDPMember::~ScDPMember()
    2600             : {
    2601             :     //! release pSource
    2602        1540 : }
    2603             : 
    2604        3245 : bool ScDPMember::IsNamedItem(SCROW nIndex) const
    2605             : {
    2606        3245 :     long nSrcDim = pSource->GetSourceDim( nDim );
    2607        3245 :     if ( nHier != SC_DAPI_HIERARCHY_FLAT && pSource->IsDateDimension( nSrcDim ) )
    2608             :     {
    2609           0 :         const ScDPItemData* pData = pSource->GetCache()->GetItemDataById(nDim, nIndex);
    2610           0 :         if (pData->IsValue())
    2611             :         {
    2612             :             long nComp = pSource->GetData()->GetDatePart(
    2613           0 :                 (long)::rtl::math::approxFloor( pData->GetValue() ),
    2614           0 :                 nHier, nLev );
    2615             :             //  fValue is converted from integer, so simple comparison works
    2616           0 :             const ScDPItemData* pData2 = GetItemData();
    2617           0 :             return pData2 && nComp == pData2->GetValue();
    2618             :         }
    2619             :     }
    2620             : 
    2621        3245 :     return  nIndex == mnDataId;
    2622             : }
    2623             : 
    2624        1493 : sal_Int32 ScDPMember::Compare( const ScDPMember& rOther ) const
    2625             : {
    2626        1493 :     if ( nPosition >= 0 )
    2627             :     {
    2628          89 :         if ( rOther.nPosition >= 0 )
    2629             :         {
    2630             :             OSL_ENSURE( nPosition != rOther.nPosition, "same position for two members" );
    2631          88 :             return ( nPosition < rOther.nPosition ) ? -1 : 1;
    2632             :         }
    2633             :         else
    2634             :         {
    2635             :             // only this has a position - members with specified positions come before those without
    2636           1 :             return -1;
    2637             :         }
    2638             :     }
    2639        1404 :     else if ( rOther.nPosition >= 0 )
    2640             :     {
    2641             :         // only rOther has a position
    2642           3 :         return 1;
    2643             :     }
    2644             : 
    2645             :     // no positions set - compare names
    2646        1401 :    return pSource->GetData()->Compare( pSource->GetSourceDim(nDim),mnDataId,rOther.GetItemDataId());
    2647             : }
    2648             : 
    2649        7837 : void ScDPMember::FillItemData( ScDPItemData& rData ) const
    2650             : {
    2651             :     //! handle date hierarchy...
    2652             : 
    2653        7837 :     const ScDPItemData* pData = GetItemData();
    2654        7837 :     rData = (pData ? *pData : ScDPItemData());
    2655        7837 : }
    2656             : 
    2657         530 : const OUString* ScDPMember::GetLayoutName() const
    2658             : {
    2659         530 :     return mpLayoutName.get();
    2660             : }
    2661             : 
    2662           0 : long ScDPMember::GetDim() const
    2663             : {
    2664           0 :     return nDim;
    2665             : }
    2666             : 
    2667         824 : OUString ScDPMember::GetNameStr() const
    2668             : {
    2669         824 :     const ScDPItemData* pData = GetItemData();
    2670         824 :     if (pData)
    2671         824 :         return pSource->GetData()->GetFormattedString(nDim, *pData);
    2672           0 :     return OUString();
    2673             : }
    2674             : 
    2675         812 : OUString SAL_CALL ScDPMember::getName() throw(uno::RuntimeException)
    2676             : {
    2677         812 :     return GetNameStr();
    2678             : }
    2679             : 
    2680           0 : void SAL_CALL ScDPMember::setName( const OUString& /* rNewName */ ) throw(uno::RuntimeException)
    2681             : {
    2682             :     OSL_FAIL("not implemented");        //! exception?
    2683           0 : }
    2684             : 
    2685       15045 : bool ScDPMember::isVisible() const
    2686             : {
    2687       15045 :     return bVisible;
    2688             : }
    2689             : 
    2690        1234 : bool ScDPMember::getShowDetails() const
    2691             : {
    2692        1234 :     return bShowDet;
    2693             : }
    2694             : 
    2695             : // XPropertySet
    2696             : 
    2697           0 : uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDPMember::getPropertySetInfo()
    2698             :                                                         throw(uno::RuntimeException)
    2699             : {
    2700           0 :     SolarMutexGuard aGuard;
    2701             : 
    2702             :     static SfxItemPropertyMapEntry aDPMemberMap_Impl[] =
    2703             :     {
    2704           0 :         {MAP_CHAR_LEN(SC_UNO_DP_ISVISIBLE), 0,  &getBooleanCppuType(),              0, 0 },
    2705           0 :         {MAP_CHAR_LEN(SC_UNO_DP_POSITION), 0,  &getCppuType((sal_Int32*)0),        0, 0 },
    2706           0 :         {MAP_CHAR_LEN(SC_UNO_DP_SHOWDETAILS), 0,  &getBooleanCppuType(),              0, 0 },
    2707           0 :         {MAP_CHAR_LEN(SC_UNO_DP_LAYOUTNAME), 0, &getCppuType(static_cast<OUString*>(0)), 0, 0 },
    2708             :         {0,0,0,0,0,0}
    2709           0 :     };
    2710             :     static uno::Reference<beans::XPropertySetInfo> aRef =
    2711           0 :         new SfxItemPropertySetInfo( aDPMemberMap_Impl );
    2712           0 :     return aRef;
    2713             : }
    2714             : 
    2715         485 : void SAL_CALL ScDPMember::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
    2716             :                 throw(beans::UnknownPropertyException, beans::PropertyVetoException,
    2717             :                         lang::IllegalArgumentException, lang::WrappedTargetException,
    2718             :                         uno::RuntimeException)
    2719             : {
    2720         485 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
    2721         233 :         bVisible = lcl_GetBoolFromAny(aValue);
    2722         252 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
    2723         200 :         bShowDet = lcl_GetBoolFromAny(aValue);
    2724          52 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    2725          52 :         aValue >>= nPosition;
    2726           0 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2727             :     {
    2728           0 :         OUString aName;
    2729           0 :         if (aValue >>= aName)
    2730           0 :             mpLayoutName.reset(new OUString(aName));
    2731             :     }
    2732             :     else
    2733             :     {
    2734             :         OSL_FAIL("unknown property");
    2735             :     }
    2736         485 : }
    2737             : 
    2738         282 : uno::Any SAL_CALL ScDPMember::getPropertyValue( const OUString& aPropertyName )
    2739             :                 throw(beans::UnknownPropertyException, lang::WrappedTargetException,
    2740             :                         uno::RuntimeException)
    2741             : {
    2742         282 :     uno::Any aRet;
    2743         282 :     if ( aPropertyName.equalsAscii( SC_UNO_DP_ISVISIBLE ) )
    2744         125 :         lcl_SetBoolInAny(aRet, bVisible);
    2745         157 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_SHOWDETAILS ) )
    2746          33 :         lcl_SetBoolInAny(aRet, bShowDet);
    2747         124 :     else if ( aPropertyName.equalsAscii( SC_UNO_DP_POSITION ) )
    2748           0 :         aRet <<= nPosition;
    2749         124 :     else if (aPropertyName.equalsAscii(SC_UNO_DP_LAYOUTNAME))
    2750         124 :         aRet <<= mpLayoutName.get() ? *mpLayoutName : OUString();
    2751             :     else
    2752             :     {
    2753             :         OSL_FAIL("unknown property");
    2754             :     }
    2755         282 :     return aRet;
    2756             : }
    2757             : 
    2758           0 : SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDPMember )
    2759             : 
    2760             : 
    2761           0 : const ScDPCache* ScDPSource::GetCache()
    2762             : {
    2763             :     OSL_ENSURE( GetData() , "empty ScDPTableData pointer");
    2764           0 :     return ( GetData()!=NULL) ? GetData()->GetCacheTable().getCache() : NULL ;
    2765             : }
    2766             : 
    2767        8661 : const ScDPItemData* ScDPMember::GetItemData() const
    2768             : {
    2769        8661 :     const ScDPItemData* pData = pSource->GetItemDataById(nDim, mnDataId);
    2770             :     SAL_WARN_IF( !pData, "sc", "ScDPMember::GetItemData: what data? nDim " << nDim << ", mnDataId " << mnDataId);
    2771        8661 :     return pData;
    2772             : }
    2773             : 
    2774        8728 : const ScDPItemData* ScDPSource::GetItemDataById(long nDim, long nId)
    2775             : {
    2776        8728 :     return GetData()->GetMemberById(nDim, nId);
    2777             : }
    2778             : 
    2779           0 : SCROW ScDPSource::GetMemberId(long nDim, const ScDPItemData& rData)
    2780             : {
    2781           0 :     return GetCache()->GetIdByItemData(nDim, rData);
    2782             : }
    2783             : 
    2784           0 : const ScDPItemData* ScDPMembers::GetSrcItemDataByIndex(SCROW nIndex)
    2785             : {
    2786           0 :     const std::vector< SCROW >& memberIds = pSource->GetData()->GetColumnEntries( nDim );
    2787           0 :     if ( nIndex >= (long )(memberIds.size()) || nIndex < 0 )
    2788           0 :         return NULL;
    2789           0 :     SCROW nId =  memberIds[ nIndex ];
    2790           0 :     return pSource->GetItemDataById( nDim, nId );
    2791             : }
    2792             : 
    2793           0 : SCROW ScDPMembers::GetSrcItemsCount()
    2794             : {
    2795           0 :     return pSource->GetData()->GetColumnEntries(nDim).size();
    2796          93 : }
    2797             : 
    2798             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10