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