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