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