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

Generated by: LCOV version 1.10