LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - dptabsrc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 912 1330 68.6 %
Date: 2012-12-27 Functions: 131 203 64.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10