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